~~并发编程(十二):死锁和递归锁~~

进击の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()


*****
*****
原文地址:https://www.cnblogs.com/jevious/p/11411133.html