cpython 解释器执行代码
python 代码的执行有 python 虚拟机进行控制的, python解释器可以运行多个线程,但在任意给定时刻只有一个线程会被解释器执行
对于Python虚拟机的访问有全局解释器锁(GIL)控制的,
这个锁就是用来保证同时只有一个线程被运行的
复制代码
GIL 锁的主要流程
1. 设置GIL
2. 切换到一个线程去执行
3. 执行下面的操作
a.执行python的非IO程序(cpu计算)
b.执行IO相关(发生阻塞),线程让出控制权
4.线程进入睡眠状态(切换出线程)
5.解锁GIL
6.重复1-5
复制代码
总结
python, 特指CPython的实现,由于GIL的存在,python 多线程不能有效的利用多核处理器。 表现为任意时间只有一个线程在跑,而IO密集型运算,多数是在IO读写将线程阻塞掉了, 这个时候线程切换是很合理的,反正线程只是单纯地等待,在这个等待的时候去做其他的事情, 资源利用率就上去了.对于多进程,因为每个进程都有独立的GIL,就可以利用多核的特性处理 CPU密集的操作
IO(Input/ Output)密集:多线程 (网络IO,磁盘IO)等
CPU密集:多进程 纯计算(分布式计算)
测试
-
生成一个线程类继承 分别测试 单线程和多线程下的IO密集和CPU密集的时间
import threading import time class MyThread(threading.Thread): def __init__(self,func,args, name): super(MyThread,self).__init__() self.func = func self.args = args self.name = name def get_res(self): return self.result def run(self): self.result = self.func(*self.args) ###################### def sum1(start, end): ans = 0 for i in range(start,end+1) ans += i return ans # 执行写入操作 def openIO(end): for i in range(0,end): fd = open('1','w') fd.write('s') fd.close() # 单线程cpu def singleThread(start,end): print("sing thread start") t_start = time.time() ans = 0 for i in range(start,end+1): ans += i t_stop = time.time() print("ans = %d" % ans) print("single thread done cost:%.2fd" % (t_stop - t_start)) # 多线程 cpu def multiThread(): print("mutli thread start") t_start = time.time() nums = [(1, 100000000), (100000001, 200000000), (200000001, 300000000)] threads = [] for i in range(0,len(nums)): t = MyThread(sum1,nums[i], sum1.__name__) threads.append(t) for i in range(len(threads)): threads[i].join() ans += threads[i].get_res() t_end = time.time() print(ans) print("multi thread done cost:%.2f" % (t_end - t_start)) # CPU 运算 def CPUslove(): singleThread(1,300000000) multiThread() def IOSingle(): print("IO single start") t_start = time.time() openIO(55000) openIO(35000) t_end = time.time() print("io single done cost %.2f" % (t_end - t_start)) def IOMulti(): print("IO multi start") t_start = time.time() t1 = MyThread(openIO, (55000,),openIO.__name__) t2 = MyThread(openIO, (35000,),openIO.__name__) t1.start() t2.start() t1.join() t2.join() t_end = time.time() print("io multi done cost %.2f" % (t_end - t_start)) def IOSlove(): IOMulti() IOSingle() def main(): IOSlove() CPUSlove() if __name__ == '__main__': main() 复制代码
-
结果如下图所示: