概述
1、无法利用多核
Python的多线程是无法只用多核进行运算,(多进程可以) 【具体原因是GIL锁,取得GIL锁的进程才能运行,但一个进程的Python只有一个GIL】 【GIL 全局解释器锁】
2、无需通信
在各个子线程中,是可以直接调用到主线程的全局变量等 (可以把各个子线程看作同步运行的普通函数即可)
带来的问题: 假如有多条子线程同时运行,但他们又都会对全局变量A进行修改,且结果不同 这会导致全局变量A的结果随机 【为了放在这种事情发生,必须加一个Lock】
threading:线程模块
threading.Thread 线程类
用法和Process进程类基本差不多 创建的对象也有 strat( )、join( )方法,就连类的构造方法用法都基本差不多
【Thread类构造方法:threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)】 【Process类构造方法:Process(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)】 所以具体怎么用,去上一篇参考多进程即可
唯一的区别是,线程可以调用全局变量
import threadingdef func():print("子进程")t = threading.Thread(target=func,args=())t.start()t.join()# 输出#=========================子进程
threading.Lock 线程锁类
为了防止“多条子线程同时运行,又同时又对全局变量进行修改” 我们需要使用Lock类,将线程锁起来。
当线程拥有线程锁时,其他线程是无法被运行的,只有当线程锁被释放才能运行。 注意:一个进程只能拥有一个线程锁
类方法: acquire( ):加锁 release( ):释放锁
import threadingimport randomimport timedef func(x):time.sleep(random.randint(0,10)*0.1) #给进程一个随机增加运行时长print("子进程:",x)for i in range(10):t = threading.Thread(target=func,args=(i,))t.start()print("主线程")#输出#===============================子进程: 5主线程子进程: 1子进程: 6子进程: 8子进程: 4子进程: 9子进程: 2子进程: 3子进程: 0子进程: 7
分析: 输出结果变得无序,那是因为所有的子线程可以看作是“同步执行的”
假如调用了一个全局变量,而且每个线程在结束前都对全局变量进行不同的修改, 这个变量最后的值将取决于最后一个执行完成的线程 但线程的运行时长是随机的,结果就导致全局变量结果是随机的
Lock的作用: 假如为线程添加一个Lock,当子线程运行时, 就必须等待上一个线程运行到锁被释放,下一个线程才能继续运行
import threadingimport randomimport timemylock=threading.Lock()def func(x):mylock.acquire() #加线程锁time.sleep(random.randint(0,10)*0.1)print("子进程:",x)mylock.release() #释放线程锁for i in range(10):t = threading.Thread(target=func,args=(i,))t.start()time.sleep(3)print("主线程")# 输出#================================子进程: 0子进程: 1子进程: 2子进程: 3子进程: 4主线程子进程: 5子进程: 6子进程: 7子进程: 8子进程: 9
主线程也是包括在内的, 在上一个线程锁释放之后,所有待运行的进程都会开始运行,包括主线程
+【关于GIL】
GIL是一个进程的全局线程锁,这个线程锁每隔一段时间就会释放一次,用于切换其他线程运行, 以此达到单核CPU运行多个线程的目的 但是是Python中一个进程只有一个GIL,那就意味着, 1、一个进程在同一时间只有一个线程在运行, 2、只是GIL释放和加锁的频率速度很快,让人误以为线程之间是同步进行的 3、Python的线程无法利用多核CPU
在Python2.7之前是可以通过sys.setcheckinterval( )方法来改变GIL的速度,但Python3已经弃用了这个方法
threading.local 本地储存
local类的作用: 将子线程的局部变量储存在,主线程中 使用local对象创建的变量,其他线程不可用(主线程中也一样)
如何使用Local类的对象去创建变量: 绑定
import threadingimport randomimport timevalue_Local = threading.local()# 创建本地储存(用于保存线程的局部变量)value_Local.x = "不可见" # 主线程的局部变量(子线程不可见)def func(x):value_Local.y = x # 在线程中创建局部变量(其他线程不可见)print("子进程:",value_Local.y)for i in range(10):t = threading.Thread(target=func,args=(i,))t.start()
其实这一块我不是很理解, Local的作用是在主线程中创建一个子线程才能用的局部变量, 但事实上,我可以直接在子线程中创建局部变量。
因此我不是很理解Local的作用。 但我大致猜测,如果尝试在子线程新建一个局部变量, 有可能会导致一些问题,因此把创建的过程放在的主线程中。
这是官方文档的描述: (就这么点内容)

