day9-递归锁(RLock)
一、概述
我们今天来聊聊递归锁,到底什么是递归锁,为什么会存在?
二、递归锁(RLock)
2.1、前戏
说明:比如你进学校去班级,结果进学校的时候有一道门,进班级的时候又有一道门,你首先进入学校要把第一道门打开,然后锁上。进入学校之后,你又要进班级的门,然后锁上。然后你出班级,就是要打开第二把锁,然后再出校门打开第一把锁。但是这边有一个疑问,就是你在开锁的时候,两把锁的钥匙是一样的,也就是你被困在里面了,出不来了。多重锁把你完美的锁在里面了。代码如下:
import threading def run1(): print("grab the first part data") lock.acquire() #修改num前加锁 global num num +=1 lock.release() #释放锁 return num def run2(): print("grab the second part data") lock.acquire() #修改num2前加锁 global num2 num2+=1 lock.release() #释放锁 return num2 def run3(): lock.acquire() #加锁 res = run1() #执行run1函数 print('--------between run1 and run2-----') res2 = run2() #执行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() while threading.active_count() != 1: #判断是否只剩主线程了 print(threading.active_count()) else: print('----all threads done---') print(num,num2)
上面的执行结果,是无限的进入死循环,所以不能这么加。那咋办呢?下面我们就来说说递归锁。
2.2、递归锁(RLock)
说明:递归锁的意思就是一把大锁还要包含子锁。用theading.RLock()设置递归锁。
import threading def run1(): print("grab the first part data") lock.acquire() #修改num前加锁 global num num +=1 lock.release() #释放锁 return num def run2(): print("grab the second part data") lock.acquire() #修改num2前加锁 global num2 num2+=1 lock.release() #释放锁 return num2 def run3(): lock.acquire() #加锁 res = run1() #执行run1函数 print('--------between run1 and run2-----') res2 = run2() #执行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)
看看执行结果,没有存在这种问题了。
2.3、递归锁原理
原理其实很简单的:就是递归锁,每开一把门,在字典里面存一份数据,退出的时候去到door1或者door2里面找到这个钥匙退出就OK了。
lock = { door1:key1, door2:key2 }
逻辑图:
四、总结
递归锁用于多重锁的情况,如果只是一层锁,我们不用。在实际情况下,递归锁场景用的不是特别多,所以知道就行了。