目录
1、什么是GIL
GIL的全称是 Global Interpreter Lock,全局解释器锁
python的执行依赖于解释器,解释器基于不同编程语言有不同的版本
基于C/C++语言编写的python解释器为Cpython,设计时,为了保证多线程之间数据完整性与状态同步,设计为在任意时刻同一个进程内只有一个线程可以访问该进程内的共享数据,由GIL来控制实现
2、GIL与互斥锁Lock
GIL本质上也是互斥锁,保护的是解释器级别的数据,或者说保护的是进程内的共享数据(全局变量)
注意点:
GIL是解释器自动实现,互斥锁Lock需要开发者自行添加
- 当申请到GIL全局解释器锁的进程进入阻塞态(即遇到IO操作),GIL会立即失效,别的进程就可以申请GIL
GIL不会保护用户自己的数据,需要开发者自己添加互斥锁
3、GIL与多线程
3.1 CPU执行程序的效率
- cpu可以做计算和I/O
- 多核cpu可以同时进行计算,能够有效的提升计算效率
- cpu遇到I/O时,肯定会让线程进入阻塞态,就算是多核,也仍需等待,所以多核不能提升I/O速率
即:对计算来说,cpu越多越好,但是对于I/O来说,再多的CPU也没用
3.2 多进程与多线程的差别
消耗资源:
开启线程远小于开启进程
切换线程远小于切换进程
Cpython多线程只能实现并发,但是多进程可以实现并发
结合cpu执行程序的效率,将程序分为计算密集型与I/O密集型来讨论
3.2.1 计算密集型
计算密集型
由于计算操作较多,所以程序的执行效率取决于CPU的计算性能
单核:都是并发执行,并且I/O操作较少,所以执行效率时相差不多的,相差的执行时间基本上就是开启进程与开启线程的差别
多核:由于多进程可以实现并行,所以当任务越多,多核在计算性能上的提升越明显
3.2.2 I/O密集型
I/O密集型
由于I/O操作较多,所以程序的执行速率取决于CPU的I/O性能
单核:多进程也只能实现并发,此时,多线程与多进程的差别,只有在遇到I/O时切换的效率差别了,很明显,多线程的效率要高的多
多核:CPU在遇到I/O操作时,必须等待I/O,因此多核多I/O的性能提升不大,此时多线程与多进程的差别,也取决于遇到I/O是的切换效率了,很明显,当任务量越多,多线程的效率越高
3.2.3 代码演示
计算密集型
from multiprocessing import Process
from threading import Thread
import time,os
def work():
res = 0
for i in range(100000000):
res += 1
print(res)
if __name__ == '__main__':
l = []
print(os.cpu_count())
start_time = time.time()
for i in range(1):
p = Process(target=work)
# p = Thread(target=work)
l.append(p)
p.start()
for p in l:
p.join()
stop_time = time.time()
print(f'消耗时间:{stop_time-start_time}')
I/O密集型
from multiprocessing import Process
from threading import Thread
import time,os
def work(i):
time.sleep(0.1)
print(i)
if __name__ == '__main__':
l = []
print(os.cpu_count())
start_time = time.time()
for i in range(100):
p = Process(target=work,args=(i,))
# p = Thread(target=work,args=(i,))
l.append(p)
p.start()
for p in l:
p.join()
stop_time = time.time()
print(f'消耗时间:{stop_time-start_time}')