~~并发编程(十二):死锁和递归锁~~
进击のpython
并发编程——死锁和递归锁
死锁是一种现象:
两个及以上的进程或者线程在争抢资源的过程中,出现的互相等待的现象
如果没有外部干预,他们就一直僵持,永远在互相等待,就“死”住了
看一下现象:
from threading import Thread, Lock
def func(A, B):
A.acquire()
print('A:这是func函数的开始.. ..')
B.acquire()
print('B:这是func函数的开始.. ..')
B.release()
print('B:这是func函数的结束!')
A.release()
print('A:这是func函数的结束!')
def inner(A, B):
B.acquire()
print('A:这是inner函数的开始.. ..')
A.acquire()
print('B:这是inner函数的开始.. ..')
A.release()
print('B:这是inner函数的结束!')
B.release()
print('A:这是inner函数的结束!')
def main(A, B):
func(A, B)
inner(A, B)
if __name__ == '__main__':
A = Lock()
B = Lock()
for i in range(10):
t = Thread(target=main, args=(A, B))
t.start()
执行的时候就会出现阻塞情况(自己执行)
那我也想保护func里面的数据,也想保护inner里面的数据,应该怎么办?
递归锁
为了解决上述问题,递归锁应运而生
为了支持在同一线程中多次请求同一资源,python就提供了重入锁RLock
这个锁就很有意思,他里面除了互斥锁Lock以外,还有一个计数器counter
counter记录了acquire的次数,从而使得资源可以被多次require
直到一个线程所有的acquire都被release,其他的线程才能获得资源
上面的例子如果使用RLock代替Lock,则不会发生死锁
二者的区别是:递归锁可以连续acquire多次,而互斥锁只能acquire一次
from threading import Thread, RLock
def func(A, B):
A.acquire()
print('A:这是func函数的开始.. ..')
B.acquire()
print('B:这是func函数的开始.. ..')
B.release()
print('B:这是func函数的结束!')
A.release()
print('A:这是func函数的结束!')
def inner(A, B):
B.acquire()
print('B:这是inner函数的开始.. ..')
A.acquire()
print('A:这是inner函数的开始.. ..')
A.release()
print('A:这是inner函数的结束!')
B.release()
print('B:这是inner函数的结束!')
def main(A, B):
func(A, B)
inner(A, B)
if __name__ == '__main__':
B = A = RLock() # 区别在这!
for i in range(10):
t = Thread(target=main, args=(A, B))
t.start()