线程
线程理论
1.进程是资源单位
进程相当于是车间,进程负责给内部的线程提供相应的资源
2.线程是执行单位
线程相当于是车间里面的流水线,线程负责执行真正的功能
3.一个进程至少含有一个线程
4.多进程与多线程的区别
多进程
需要申请内存空间,需要拷贝全部代码,资源消耗大
多线程
不需要申请内存空间,不需要拷贝全部代码,资源消耗小
3.同一个进程下多个线程之间资源共享
创建线程的方式
"""
1.双击桌面程序图标
2.代码创建进程(需要掌握)
需要掌握两种即可
"""
from threading import Thread
import time
def task(name):
print(f'{name}开始运行')
time.sleep(1) # 运行线程
print(f'{name}结束运行')
if __name__ == '__main__': # 启动脚本
p = Thread(target=task, args=('game',)) # 创建一个线程对象
p.start() # 子线程开始执行
print('主线程结束')
# game开始运行
# 主线程结束
# game结束运行
task('game') # 直接函数调用是同步操作
print('主线程结束')
# game开始运行
# game结束运行
# 主线程结束
'''
开设线程不需要完整拷贝代码,使所以无论什么系统都不会出现反复操作的情况
不需要启动脚本,但是为了兼容性,也可以用
'''
class MyThread(Thread):
def __init__(self, name):
super().__init__()
self.name = name
def run(self):
print(f'{self.name}开始运行')
time.sleep(1) # 运行线程
print(f'{self.name}结束运行')
if __name__ == '__main__':
obj = MyThread('game')
obj.start() # 子线程开始执行
print('主线程结束')
# game开始运行
# 主线程结束
# game结束运行
join方法
'join:主线程等待子线程运行结束之后再运行'
from threading import Thread
import time
def task():
print('开始运行')
time.sleep(1) # 运行线程
print('结束运行')
if __name__ == '__main__': # 启动脚本
p = Thread(target=task) # 创建一个线程对象
p.start() # 子线程开始执行
p.join()
print('主线程结束')
# 开始运行
# 结束运行
# 主线程结束
线程间数据共享
'同一个进程下的线程之间的数据是共享的'
from threading import Thread
money = 666
def task():
global money
money = 233
print(money)
if __name__ == '__main__':
p = Thread(target=task)
p.start()
p.join()
print(money)
# 233
# 233
线程相关方法
1.进程号
同一个进程下开设的多个线程拥有相同的进程号
2.线程名
from threading import Thread, current_thread
current_thread().name
主线程:MainThread 子线程:Thread-N
3.进程下的线程数
active_count()
4.例子
from threading import Thread, current_thread
def task():
print(current_thread().name)
if __name__ == '__main__':
p = Thread(target=task)
p.start()
p.join()
print(current_thread().name)
# Thread-1
# MainThread
守护线程
'被守护线程结束时,守护线程立刻结束'
from threading import Thread
import time
def task():
print('开始运行')
time.sleep(3) # 运行线程
print('结束运行')
if __name__ == '__main__': # 启动脚本
p = Thread(target=task) # 创建一个线程对象
p.daemon = True # 将子线程设置为守护线程(必须在start之前执行)
p.start() # 子线程开始执行
print('主线程结束')
# 开始运行
# 主线程结束
GIL全局解释器锁
储备知识
1.python解释器也是由编程语言写出来的
Cpython 用C写出来的
Jpython 用Java写出来的
Pypython 用python写出来的
ps:最常用的就是Cpython(默认)
2.官方文档对GIL的解释
In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)
"""
1.GIL的研究是Cpython解释器的特点 不是python语言的特点
2.GIL本质也是一把互斥锁
3.GIL的存在使得同一个进程下的多个线程无法同时执行(关键),也就是说单进程下的多线程无法利用多核优势!
4.GIL的存在主要是因为cpython解释器中垃圾回收机制不是线程安全的
"""
3.python的多线程虽然无法使用多核优势,但是在IO密集型的任务下是有用的
4.GIL只确保解释器层面数据不会错乱(垃圾回收机制),程序中自己的数据应该自己加锁处理
5.所有的解释型编程语言都没办法做到同一个进程下多个线程同时执行