一  死锁现象
 
  所谓死锁:是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,如下就是死锁
 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | fromthreading importThread, Lock
 importtime
 mutexA =Lock()
 mutexB =Lock()
 classMyThread(Thread):
     defrun(self):
         self.func1()
         self.func2()
     deffunc1(self):
         mutexA.acquire()
         print('\033[41m%s 拿到A锁\033[0m'%self.name)
         mutexB.acquire()
         print('\033[42m%s 拿到B锁\033[0m'%self.name)
         mutexB.release()
         mutexA.release()
     deffunc2(self):
         mutexB.acquire()
         print('\033[43m%s 拿到B锁\033[0m'%self.name)
         time.sleep(3)
         mutexA.acquire()
         print('\033[44m%s 拿到A锁\033[0m'%self.name)
         mutexA.release()
         mutexB.release()
     
 if__name__ =='__main__':
     fori inrange(10):
         t =MyThread()
         t.start()
 | 
 
  执行效果
 
| 1 2 3 4 | Thread-1拿到A锁
 Thread-1拿到B锁
 Thread-1拿到B锁
 Thread-2拿到A锁        # 出现死锁,整个程序阻塞
 | 
 
  
 
二 递归锁
 
解决方法,递归锁,在Python中为了支持在同一线程中多次请求同一资源,Python提供了可重入锁RLock
 
这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其它的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁,二者的区别是:递归锁可以连续acquire多次,而互斥锁只能acquire一次
 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | # 递归锁
 fromthreading importThread, RLock
 importtime
 mutexA =mutexB =RLock()       # 一个线程拿到锁,counter加1,该线程内又碰到加锁的情况,则counter继续加1,这期间所有其他线程都只能等待,等待该线程释放所有锁,即counter递减到0为止
 classMyThread(Thread):
     defrun(self):
         self.func1()
         self.func2()
         
     deffunc1(self):
         mutexA.acquire()
         print('\033[41m%s 拿到A锁\033[0m'%self.name)
         mutexB.acquire()
         print('%s 拿到B锁'%self.name)
         mutexB.release()
         mutexA.release()
     deffunc2(self):
         mutexB.acquire()
         print('\033[43m%s 拿到B锁\033[0m'%self.name)
         mutexA.acquire()
         print('%s 拿到A锁'%self.name)
         mutexA.release()
         mutexB.release()
 if__name__ =='__main__':
     fori inrange(10):
         t =MyThread()
         t.start()
 |