In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.
在Cpython中,GIL这个全局解释器锁就是一个互斥锁,一次只能让一个线程运行。这把锁是必须且重要的是因为Cpython解释器的内存管理对线程来说并不是一个安全的。
然而,自从GIL存在,其他特性已经成长为依赖于它强制执行的保证。(就是所有的线程都要去抢这把锁)
假设没有GIL这把锁的情况下,会出现的情况!!!
* 为什么要有GIL是因为它内部的垃圾回收机制不是线程安全的
* 垃圾回收机制也是一个任务,跟你的代码不是串行运行,如果是串行会明显有卡顿
* 这个垃圾回收到底是开进程还是开线程?肯定是线程,线程肯定也是一段代码,所以想运行也必须要拿到python解释器
* 假设能够并行,会出现什么情况?一个线程刚好要造一个a=1的绑定关系之前,这个垃圾线程来扫描,矛盾点就来了,谁成功都不
1.python中的多线程到底有没有用?
单核情况下:四个任务
多核情况下:四个任务
计算密集型:一个任务算十秒,四个进程和四个线程,肯定是进程快
IO密集型:任务都是纯io情况下,线程开销比进程小,肯定是线程好
import os,time from multiprocessing import Process from threading import Thread ''' 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):#产生8个进程同时执行 p=Thread(target=work)#run time is 39.95239758491516 # p=Process(target=work) #run time is 8.076356410980225 l.append(p) p.start() for p in l: p.join() stop=time.time() print('run time is %s'%(stop-start)) ''' #io密集型 def work(): time.sleep(2) if __name__ == '__main__': start=time.time() l=[] for i in range(600): #开启600个线程 p=Process(target=work) #run time is 11.53145694732666 # p=Thread(target=work) #run time is 2.06762957572937 l.append(p) p.start() for p in l: p.join() stop=time.time() print('run time is %s'%(stop-start))
GIL全局锁和普通锁的区别
# from threading import Thread,Lock # import time # # mutex=Lock() # # # n=100 # # def task(): # # global n # mutex.acquire() # temp=n # time.sleep(0.1) # n=temp-1 # mutex.release() # # t_list=[] # for i in range(100): # t=Thread(target=task) # t.start() # t_list.append(t) # # for t in t_list: # t.join() # # print(n) # # pass ''' 对于不同的数据,要想保证安全,必须加不同的锁处理 GIL并不能保证数据的安全,它是对Cpython解释器加锁,针对的是线程 保证的是同一个进程下多个线程之间的安全 ''' from threading import Thread,Lock import time mutex=Lock() n=100 def task(): global n mutex.acquire() temp=n time.sleep(0.1) #模拟网络延迟 n=temp-1 mutex.release() l_list=[] for i in range(100): t=Thread(target=task) t.start() l_list.append(t) for t in l_list: t.join() print(n) #0
死锁和递归锁
#死锁 ''' import time from threading import Thread,Lock mutexA=Lock() mutexB=Lock() class MyThead(Thread): def run(self): self.func1() self.func2() def func1(self): mutexA.acquire() print('%s 抢到了A锁' % self.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) if __name__ == '__main__': for i in range(10): t=MyThead() t.start() ''' #递归锁(解决产生死锁现象) 引用计数0 同一个人(每引用一次,计数+1),下面的人必须等到第一个人释放锁才可以抢 # from threading import Thread,RLock # mutesA=mutexB=RLock() #抢锁之后会有一个计数,抢一次计数加1 import time from threading import Thread,RLock mutexA=mutexB=RLock() class MyThead(Thread): def run(self): self.func1() self.func2() def func1(self): mutexA.acquire() print('%s 抢到了A锁' % self.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) if __name__ == '__main__': for i in range(10): t=MyThead() t.start() ''' 自定义锁:一次acquire对应一次release, 递归锁:一次acquire可以不一定要对应release,每产生一次acquire,第一个抢到锁的人的引用计数就+1,除非第一个人释放,否则别人就不会抢到锁 递归锁是解决自定义锁出现的死锁现象 '''
信号量
#钥匙串 公共厕所 from threading import Thread,Semaphore import time,random sm=Semaphore(5) #五个厕所五把锁 def task(name): sm.acquire() print('%s 正在蹲坑'%name) #模拟蹲坑耗时 time.sleep(random.randint(1,5)) sm.release() if __name__ == '__main__': for i in range(20): t=Thread(target=task,args=('伞兵%s 号'%i,)) t.start()
event事件
from threading import Event,Thread import time event=Event() def light(): print('红灯亮着!') time.sleep(3) event.set() #解除阻塞,给我的event发了一个信号 print('绿灯亮着') def car(i): print('%s 正在等红灯了'%i) event.wait() #阻塞 print('%s 加油飙车'%i) t1=Thread(target=light) t1.start() for i in range(10): t=Thread(target=car,args=(i,)) t.start()
线程queue
import queue #普通q # q=queue.Queue(3) # q.put(1) # q.put(2) # q.put(3) # print(q.get()) # print(q.get()) # print(q.get()) # print(q.get()) #先进后出q # q=queue.LifoQueue(5) # q.put(1) # q.put(2) # q.put(3) # q.put(4) # print(q.get()) #优先级q q=queue.PriorityQueue() q.put((10,'a')) q.put((1,'b')) q.put((1,'c')) q.put((1,'a')) q.put((4,'a')) print(q.get())