学习日记0907 GIL全局解释器锁 死锁与递归锁 信号量 Event事件 线程的queue
GIL全局解释器锁(*****)
为什么会出现GIL全局解释器锁
因为Cpython解释器的垃圾回收机制不是线性安全的
通俗来讲就是同一个进程中垃圾回收线程和一些要运行的线程的并发的,如果没有GIL全局解释器锁,线程运行过程中产生的数据,会因为并发的问题而被垃圾回收机制回收,
这里要提一点为什么垃圾回收机制会回收有用的数据(前提没有GIL解释器锁,垃圾回收线程和普通线程并发),因为线程运行过程中产生了数据但是还没来得急赋变量名,或者说引用计数还没来得急改,就被垃 圾回收线程发现并且回收,这时就会产生冲突,这时我们就需要应用GIL全局解释器锁
什么是GIL全局解释器锁
全局解释器锁GIL本质就是一种互斥锁,每个进程都会有一个GIL,进程中的线程需要抢到GIL才能拿到cpython解释器的执行权限,才可以执行代码
GIL全局解释器使得在cpython中同一个进程的线程无法完成并行,只能并发. 但是不同的进程可以实现并行
自义定互斥锁和GIL全局解释器锁
那么在cpython中一个进程中即含有自义定互斥锁又有GIL全局解释器锁,它们是怎么运行的呢
前提:多线程执行同一代码
同一进程中多个线程需要先抢到GIL全局解释器锁才能运行代码,再抢到GIL之后会得到自义定锁,若在得到自义定锁之后遇到了o\i操作,此时会释放GIL锁,但是不会释放自义定互斥锁,其它的线程及时得到了GIL锁也不能执行自义定互斥锁中的代码,因为没有得到自义定互斥锁,这时GIL锁还是会回到有自定锁的线程手中,只有在有自定义互斥锁的线程执行完代码释放自定义互斥锁,并且释放了GIL锁之后其它的线程才能继续运行
死锁与递归锁现象
from threading import Thread,Lock,RLock import time # mutexA=Lock() # mutexB=Lock() mutexB=mutexA=RLock() class Mythead(Thread): def run(self): self.f1() self.f2() def f1(self): mutexA.acquire() print('%s 抢到A锁' %self.name) mutexB.acquire() print('%s 抢到B锁' %self.name) mutexB.release() mutexA.release() def f2(self): mutexB.acquire() print('%s 抢到了B锁' %self.name) time.sleep(2) mutexA.acquire() print('%s 抢到了A锁' %self.name) mutexA.release() mutexB.release() if __name__ == '__main__': for i in range(100): t=Mythead() t.start()
信号量(限制一个锁可以给多少个人使用)
from threading import Thread,Semaphore import time,random sm=Semaphore(5) def task(name): sm.acquire() print('%s 正在上厕所' %name) time.sleep(random.randint(1,3)) sm.release() if __name__ == '__main__': for i in range(20): t=Thread(target=task,args=('路人%s' %i,)) t.start()
Event事件
from threading import Thread,Event import time event=Event() def light(): print('红灯正亮着') time.sleep(3) event.set() #绿灯亮 def car(name): print('车%s正在等绿灯' %name) event.wait() #等灯绿 print('车%s通行' %name) if __name__ == '__main__': # 红绿灯 t1=Thread(target=light) t1.start() # 车 for i in range(10): t=Thread(target=car,args=(i,)) t.start()
Queue
队列型(先进先出)
queue.Queue() #先进先出 q=queue.Queue(3) q.put(1) q.put(2) q.put(3) print(q.get()) print(q.get()) print(q.get())
堆栈型(先进后出)
queue.LifoQueue() #后进先出->堆栈 q=queue.LifoQueue(3) q.put(1) q.put(2) q.put(3) print(q.get()) print(q.get()) print(q.get())
优先级型(根据优先级选择)
q=queue.PriorityQueue(3) #优先级,优先级用数字表示,数字越小优先级越高 q.put((10,'a')) q.put((-1,'b')) q.put((100,'c')) print(q.get()) print(q.get()) print(q.get())