内容概要
一、死锁与递归锁(了解)
二、信号量(了解)
三、Event事件(了解)
四、其它线程q(了解)
五、进程池与线程池
六、协程
七、协程实现TCP并发(了解)
1、死锁与递归锁
虽然互斥锁的语法看起来很简单,就是一acquire对应一release,但是在多并发情况下,使用多把互斥锁容易造成死锁现象
死锁现象例子
from threading import Thread,Lock import time # metuxA = Lock() # metuxB = Lock() # 锁A和锁B是两把不同的锁 class MyThread(Thread): def run(self): self.func1() self.func2() def func1(self): metuxA.acquire() print(‘{}抢到了锁A‘.format(self.name)) metuxB.acquire() print(‘{}抢到了锁B‘.format(self.name)) metuxA.release() metuxB.release() def func2(self): metuxB.acquire() print(‘{}抢到了锁B‘.format(self.name)) time.sleep(2) metuxA.acquire() print(‘{}抢到了锁A‘.format(self.name)) metuxA.release() metuxB.release() if __name__ == ‘__main__‘: for i in range(10): t = MyThread() t.start()
执行这个程序,会发生线程1抢了锁A,想抢锁B;但是线程2已经抢了锁B,它又想抢锁A,两个线程彼此卡住。
要想解决死锁现象,可以将所有不同的锁设置为同一把递归锁
Rlock是递归锁
from threading import Thread,RLock import time metuxA = metuxB = RLock() # 递归锁的特点: ‘‘‘ 递归锁可以被连续acquire和release,当每次acquire时,锁内部的计数器自动加一; 当每次release时,锁内部的计数器自动减一。当计数为0时,锁才能真正被释放,其它线程才能枪锁 ‘‘‘ class MyThread(Thread): def run(self): self.func1() self.func2() def func1(self): metuxA.acquire() print(‘{}抢到了锁A‘.format(self.name)) metuxB.acquire() print(‘{}抢到了锁B‘.format(self.name)) metuxA.release() metuxB.release() def func2(self): metuxB.acquire() print(‘{}抢到了锁B‘.format(self.name)) time.sleep(2) metuxA.acquire() print(‘{}抢到了锁A‘.format(self.name)) metuxA.release() metuxB.release() if __name__ == ‘__main__‘: for i in range(10): t = MyThread() t.start()
2、信号量
如果说Lock是多个人抢一把锁,那么信号量就是多个人可以抢多把锁
Semaphore是信号量
from threading import Thread,Semaphore import time import random sm = Semaphore(5) def work(i): sm.acquire() print(‘伞兵{}号准备就绪‘.format(i)) time.sleep(random.randrange(2,5)) print(‘伞兵{}号落地成盒‘.format(i)) sm.release() if __name__ == ‘__main__‘: for i in range(1,21): t = Thread(target=work,args=(i,)) t.start()
3、Event事件
一般来说,主线程会等待所有非守护线程结束之后才结束
Event事件用于实现子线程之间彼此等待,或者子线程等待主线程
from threading import Thread, Event import time event = Event() def traffic_light(): print(‘红灯亮了‘) print(event.is_set()) # 打印_flag当前的值 time.sleep(8) print(‘绿灯亮了‘) event.set() # 设置_flag为True print(event.is_set()) # 打印_flag当前的值 def car(i): print(‘{}车在等待‘.format(i)) event.wait() # 执行到这里,判断_flag的值,False时阻塞;True时同行 print(‘{}车开了‘.format(i)) if __name__ == ‘__main__‘: t2 = Thread(target=traffic_light) t2.start() for i in range(1,10): t = Thread(target=car,args=(i,)) t.start() event.clear() # 设置_flag为False
4、其它线程q
# 堆栈队列 import queue # 堆栈队列:后进先出 q = queue.LifoQueue(4) q.put(11) q.put(22) q.put(33) q.put(44) print(q.get()) print(q.get()) print(q.get()) print(q.get()) # 优先级队列 q = queue.PriorityQueue(4) q.put((22,‘wwww‘)) q.put((-2,‘eeee‘)) q.put((222,‘qqqq‘)) print(q.get()) print(q.get()) print(q.get()) ‘‘‘ 优先级队列put方法要传入一个元组,该元组第一个值表示数据提取的优先级,可以为负数,且数字越小,优先级越高‘‘‘
5、线程池与进程池
原文:https://www.cnblogs.com/laijianwei/p/14446303.html