zoukankan      html  css  js  c++  java
  • ~~并发编程(十二):死锁和递归锁~~

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

    *****
    *****
  • 相关阅读:
    【转载】分析商品日均销量(DMS)对促销商品选择的意义
    日志备份和差异备份还原中的常见问题示例(转自&邹建)
    SQL Server 2000中的完整备份、差异备份操作
    数据库差异备份与增量备份的不同之处
    差异备份和还原操作方法(转)
    SQL备份(全)
    Microsoft SQL2000 错误代码 (@@error)
    图解SQL的inner join(join)、left join、right join、full outer join、union、union all的区别
    arm-none-linux-gnueabi-gcc command not found
    关于ST-Link的internal command error问题的解决方法
  • 原文地址:https://www.cnblogs.com/jevious/p/11411133.html
Copyright © 2011-2022 走看看