GIL 全局解释器锁
1.GIL全局解释器锁 =》 多进程vs多线程(*****)
GIL global interpreter Lock
1.1 GIL介绍
1.1.1 什么是GIL(cpython解释器才有)
GIL本质就是一把互斥锁,既然是互斥锁,原理都一样,都是让多个并发线程同一时间只能有一个执行。
即:有了GIL的存在,同一进程内的多个线程同一时刻只能有一个在运行。意味着在cpython中一个进程下的多个线程
无法实现并行,但是不影响并发的实现 =》无法利用多核优势???
GIL可以被比喻成执行权限,同一进程下的所有线程想要执行必须先取得执行权限。
1.1.2 为什么要有GIL
因为cpython解释器自带垃圾回收机制不是线程安全的 ==》对共享数据的修改垃圾回收线程和其他线程是共享的(在并行情况下)
在解释器代码里加锁,所有的线程都执行解释器的代码
线程调度:操作系统(本质代码、应用程序) =》调度原生线程 应用软件也可以调度,但是操作系统调度也很完整了。
GIL只是为了防止垃圾回收机制变得线程安全,想让自己的共享数据变的安全,就得给自己的数据加不同的锁。
GIL可以当作执行权限,先争夺GIL,会在任务无法执行的情况下,会强行被释放。自定义互斥锁即便无法执行
也不会被自动释放。
垃圾回收线程是python解释器里自带的线程。
简单说明下同一个进程内多个线程抢锁的一个流程:线程要执行的代码经过解释器中代码的转变变成解释器能够执行的代码(要执行的代码文本放到python解释器里),
启动多个线程,多个线程开始争抢GIL锁,先抢到的先执行,执行完释放掉GIL,如果时间过长操作系统自动释放GIL锁给别的线程争抢,抢到了重复上面执行。如果垃圾回收线程
抢到了,就回收引用计数为0的数据。
流程:因为是在同一个进程内,所以他的数据是共享的。线程申请GIL,开始执行python解释器的代码,解释器发送开启线程的请求给操作系统,操作系统
开启线程,并给线程分配cpu,开始执行线程里的代码,如果代码本身也有互斥锁,第一个获得GIL的线程先进入内部的互斥锁,执行里面的代码,如果遇到I/O
或者占用时间过长,操作系统会主动取得他的cpu,并且释放掉GIL,其他线程会取得GIL,但是遇到互斥锁还是停下来,因为内部互斥锁没有被释放,时间长了
GIL会被回收。然后其他线程又开始争抢GIL。此时如果执行完I/O操作的上一个线程,又会跑到解释器里抢GIL,抢到了他会从上次保存的状态继续运行,程序运行完毕他会释放掉内部互斥锁,同时count+1。第二个线程此时抢到GIL,拿到 count = 1,开始重复上面的步骤。
作为应用软件,解释器本来应该
越是困难的事越要立即去做,这样收益才会最大!!!