GIL全局解释器锁
Python解释器有很多种,最常见的就是CPython解释器
GIL本质也是一把互斥锁:将并发变成串行,牺牲效率保证数据的安全
用来阻止同一个进程下的 多个线程的 同时执行
(同一个进程内的多个线程无法实现并行,但是可以实现并发)
Python的多线程没法利用多核优势,是不是就没有用了?
GIL的存在是因为CPython解释器的内存管理不是线程安全的
垃圾回收机制:
a. 引用计数
b. 标记清除
c. 分代回收
研究Python的多线程是否有用,需要分情况讨论:
(假设有四个任务,每个任务需要10s 处理完成) 1. 计算密集型: 单核情况下: 开线程更省资源(原因是开进程需要申请内存空间等操作,浪费时间) 多核情况下: 开进程处理 10s 开线程处理 40s 2. I/O密集型: 单核情况下: 开线程更省资源(原因和计算密集型的一样) 多核情况下: 开线程更省资源 (原因是 I/O秘籍情况下,线程工作方式为 切换+保存 进程申请内存空间,是要消耗很长时间的, 而线程的切换+保存基本不消耗时间) python的多线程到底有没有用 需要看情况而定 并且肯定是有用的 多进程+多线程配合使用
# I/O密集型 from multiprocessing import Process from threading import Thread import threading import os,time def work(): time.sleep(2) if __name__ == '__main__': l=[] print(os.cpu_count()) # 本机为8核 start=time.time() for i in range(400): p=Process(target=work) # 耗时9.506524085998535s多,大部分时间耗费在创建进程上 # p=Thread(target=work) # 耗时 2.0459132194519043 s多 l.append(p) p.start() for p in l: p.join() stop=time.time() print('run time is %s' %(stop-start))
# 计算密集型 from multiprocessing import Process from threading import Thread import os,time def work(): res=0 for i in range(100000000): res *= i if __name__ == '__main__': l=[] print(os.cpu_count()) # 本机为8核 start=time.time() for i in range(8): p=Process(target=work) # 耗时 8.460614204406738s # p=Thread(target=work) # 耗时 34.822699308395386s l.append(p) p.start() for p in l: p.join() stop=time.time() print('run time is %s' %(stop-start))
死锁
1. 代码表示下一步要acquire一个锁 2. 但是两个线程互相拿着对方需要的锁,于是程序就hang到这儿了 这种情况就是死锁
from threading import Thread, Lock, current_thread import time mutexA = Lock() mutexB = Lock() class MyThread(Thread): # 创建线程自动触发run方法 run方法内调用func1 func2相当于也是自动触发 def run(self): self.func1() self.func2() def func1(self): mutexA.acquire() print('%s抢到了A锁'%self.name) # self.name等价于current_thread().name mutexB.acquire() print('%s抢到了B锁'%self.name) mutexB.release() print('%s释放了B锁'%self.name) mutexA.release() print('%s释放了A锁'%self.name) def func2(self): mutexB.acquire() print('%s抢到了B锁'%self.name) time.sleep(1) mutexA.acquire() print('%s抢到了A锁' % self.name) mutexA.release() print('%s释放了A锁' % self.name) mutexB.release() print('%s释放了B锁' % self.name) for i in range(10): t = MyThread() t.start() '''执行结果: Thread-1抢到了A锁 Thread-1抢到了B锁 Thread-1释放了B锁 Thread-1释放了A锁 Thread-1抢到了B锁 Thread-2抢到了A锁 (程序到这儿并没有结束,而是一直hang着...) '''