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


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

    *****
    *****
  • 相关阅读:
    eclipse中解决git分支合并冲突
    git 放弃本地修改,强制拉取更新
    廖雪峰Git入门教程
    如何实现Proxifier只代理部分程序
    Proxifier代理工具简介和下载
    Navicat Premium 12.0.18安装与激活
    Teamviewer远程控制
    夜神安卓模拟器下载及简介
    Fiddler2如何对Android应用进行抓包
    谷歌浏览器添加JSON-handle插件
  • 原文地址:https://www.cnblogs.com/jevious/p/11411133.html
Copyright © 2020-2023  润新知