线程
线程被称为轻量级进程,是CPU执行的最小单位
一般线程由一个父进程诞生,可以认为是在一个主进程中并行运行的一些**'迷你进程'**
- 线程的属性
一个进程中的各个线程和主进程共享同一片数据空间
相比进程而言,线程间的通信及数据共享更加容易
线程一般以并发方式进行,而且线程之间共享数据,所以可能会导致在多核心CPU下,一个数据被多个线程同时使用,使数据混淆所以还会有各种各样的同步原语来解决这样的问题,保证数据资源的稳定
主进程死亡,其中全部子线程都会死亡
线程也有自己的身份标识,但是只在当前的进程上下文中有意义,这个标示常称为TID
GIL
Python代码的执行是由Python虚拟机进行控制;进行分配内存,系统管理等等
在设计之初,这些大佬们考虑,同一时间只能由一个线程在执行;类似单核CPU系统中的多进程一样,同时只能有一个进程被CPU处理
这就引出了一个叫做GIL全局解释器锁的东西;多线程执环境下,一个线程在执行前,解释器首先会为这个线程设置GIL锁,只有被加锁的线程才会被CPU执行处理,但是这也就导致,在多核处理器下,其他线程只能是看着这个持有唯一锁的线程工作;线程工作结束,释放锁
GIL锁的存在,导致python的多线程不是实际的并发行为,只是简单的io切换和cpu时间片切换;不过好消息是,关于线程全局解释性锁GIL的问题,已经在各个版本逐步完善ceval.c
线程模块
Python3中,支持线程的有两个模块:_thread和threading;
_thread提供了基本的线程创建和锁支持
threading提供了更全面,更高级的线程管理、所以都推荐使用threading模块
虽然Python中的线程有GIL锁,但是在进行IO密集型工作时,IO等待时候,GIL锁会被释放,其他线程继续持锁工作,此外线程在进行cpu上下文切换时所需的损耗要远小于进程工作切换
- 注意:cpu密集选择多进程,io密集选择多线程
threading
import threading
t = Thread(target=None, name=None, args=(), kwargs=None)
'''
target: 线程任务函数
name: 线程名
args: 线程任务函数的参数,以位置参数形式传递
kwargs: 线程任务函数的操作,以命名参数形式传递
'''
t.name # 线程名
t.start() # 开启线程
t.join(time=None) # 阻塞等待线程执行结束
# 参数指定时,将指定阻塞多少秒,只有在daemon值True时生效
t.daemon = True # 设置守护线程
# 设置该属性True之后,如果没有join阻塞等待线程结束,主进程会直接退出,并且线程结束
t.getName() # 设置线程名称
t.setName() # 获取线程名称
t.isAlive() t.is_alive() # 判断线程是否激活
- 代码示例
from threading import Thread,Lock,currentThread
import time
def work():
time.sleep(1)
print(currentThread().name)
return 100
def main():
t1 = Thread(target=work)
t1.daemon = True
t1.start() # 启动且不回收
print('over')
if __name__ == '__main__':
main()