RLock(递归锁)
import threading, time def run1(): print("grab the first part data") lock.acquire()#进入大门后的一间屋子 global num num += 1 lock.release()#退出这间屋子 return num def run2(): print("grab the second part data") lock.acquire()#进入大门后的另一间屋子,和上个屋子平行 global num2 num2 += 1 lock.release()#退出这间屋子 return num2 def run3(): lock.acquire()#第一道门,大门 res = run1() print('--------between run1 and run2-----') res2 = run2() lock.release() print(res, res2) if __name__ == '__main__': num, num2 = 0, 0 lock = threading.Lock() for i in range(10): t = threading.Thread(target=run3) t.start() #一共11个线程 while threading.active_count() != 1: print(threading.active_count()) else:#只剩一个线程了,表示所有子线程执行完毕 print('----all threads done---') print(num, num2)
结果:
11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11
一直执行,不停的打印11......,锁死了,怎么办?其实是各个门之间的钥匙混了,所以打不开锁了,锁死了,需要以下操作才能解决。
RLock(递归锁)
说白了就是在一个大锁中还要再包含子锁
import threading, time def run1(): print("grab the first part data") lock.acquire() global num num += 1 lock.release() return num def run2(): print("grab the second part data") lock.acquire() global num2 num2 += 1 lock.release() return num2 def run3(): lock.acquire() res = run1() print('--------between run1 and run2-----') res2 = run2() lock.release() print(res, res2) if __name__ == '__main__': num, num2 = 0, 0 lock = threading.RLock()#改为递归锁 for i in range(10): t = threading.Thread(target=run3) t.start() while threading.active_count() != 1: print(threading.active_count()) else: print('----all threads done---') print(num, num2)
结果:
D:\Anaconda3\python.exe C:/Users/Administrator/Desktop/py_work/lib/aa.py grab the first part data --------between run1 and run2----- grab the second part data 1 1 grab the first part data --------between run1 and run2----- grab the second part data 2 2 grab the first part data --------between run1 and run2----- grab the second part data 3 3 grab the first part data --------between run1 and run2----- grab the second part data 4 4 grab the first part data --------between run1 and run2----- grab the second part data 5 5 grab the first part data --------between run1 and run2----- grab the second part data 6 6 grab the first part data --------between run1 and run2----- grab the second part data 7 7 grab the first part data --------between run1 and run2----- grab the second part data 8 8 grab the first part data --------between run1 and run2----- grab the second part data 9 9 grab the first part data --------between run1 and run2----- grab the second part data 10 10 ----all threads done--- 10 10 Process finished with exit code 0
概念总结:
死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程
那么怎么解决死锁现象呢?
解决方法,递归锁:在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁。
threading.Lock和threading.RLock区别:RLock允许在同一线程中被多次acquire。而Lock却不允许这种情况。注意:如果使用RLock,那么acquire和release必须成对出现,即调用了n次acquire,必须调用n次的release才能真正释放所占用的琐。