zoukankan      html  css  js  c++  java
  • PYTHON——多线程:死锁和递归锁(RLock)

    一、死锁现象

    # 在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁,
    # 因为系统判断这部分资源都正在使用,所有这两个线程在无外力作用下将一直等待下去。
    # 下面是一个死锁的例子:
    实例代码:
    import threading,time
    
    class myThread(threading.Thread):
        def doA(self):
            lockA.acquire()
            print(self.name,"gotlockA",time.ctime())
            time.sleep(3)
            lockB.acquire()
            print(self.name,"gotlockB",time.ctime())
            lockB.release()
            lockA.release()
    
        def doB(self):
            lockB.acquire()
            print(self.name,"gotlockB",time.ctime())
            time.sleep(2)
            lockA.acquire()
            print(self.name,"gotlockA",time.ctime())
            lockA.release()
            lockB.release()
    
        def run(self):
            self.doA()
            self.doB()
    
    if __name__=="__main__":
    
        lockA=threading.Lock()
        lockB=threading.Lock()
        threads=[]
        for i in range(1):
            threads.append(myThread())
        for t in threads:
            t.start()
        for t in threads:
            t.join()#等待线程结束,后面再讲。

    死锁现象就是出现了互相等待解锁,最后程序停下来不走了的现象。

    二、通过使用“递归锁RLock”解决上述死锁问题

      为了支持在同一线程中多次请求同一资源,python提供了“可重入锁”:threading.RLock。RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次acquire。直到一个线程所有的acquire都被release,其他的线程才能获得资源。

    代码实例一:

    import threading,time
    
    class myThread(threading.Thread):
        def doA(self):
            lock.acquire()
            print(self.name,"gotlockA",time.ctime())
            time.sleep(3)
            lock.acquire()
            print(self.name,"gotlockB",time.ctime())
            lock.release()
            lock.release()
    
        def doB(self):
            lock.acquire()
            print(self.name,"gotlockB",time.ctime())
            time.sleep(2)
            lock.acquire()
            print(self.name,"gotlockA",time.ctime())
            lock.release()
            lock.release()
    
        def run(self):
            self.doA()
            self.doB()
    
    if __name__=="__main__":
    
        # lockA=threading.Lock()
        # lockB=threading.Lock()
        lock = threading.RLock()
        threads=[]
        for i in range(1):
            threads.append(myThread())
        for t in threads:
            t.start()
        for t in threads:
            t.join()#等待线程结束,后面再讲。

     代码实例二:

    import time
    import threading
    class Account:
    def __init__(self, _id, balance):
    self.id = _id
    self.balance = balance
    self.lock = threading.RLock() # 在类中加锁是最根本的。

    def withdraw(self, amount): #取款
    with self.lock: #锁应该加载原子操作中。
    self.balance -= amount

    def deposit(self, amount): #存款
    with self.lock: #锁应该加载原子操作中。
    self.balance += amount

    def drawcash(self, amount):#lock.acquire中嵌套lock.acquire的场景
    with self.lock: #锁应该加载原子操作中。
    interest=0.05 # 计算利息
    count=amount+amount*interest
    self.withdraw(count) # 这里就出现了锁的嵌套,所有用RLock。

    def transfer(_from, to, amount):
    #锁不可以加在这里 因为其他的其它线程执行的其它方法在不加锁的情况下数据同样是不安全的
    _from.withdraw(amount)
    to.deposit(amount)

    alex = Account('alex',1000)
    yuan = Account('yuan',1000)

    t1=threading.Thread(target = transfer, args = (alex,yuan, 100))
    t1.start()

    t2=threading.Thread(target = transfer, args = (yuan,alex, 200))
    t2.start()

    t1.join()
    t2.join()

    print('>>>',alex.balance)
    print('>>>',yuan.balance)
     
  • 相关阅读:
    XPath使用示例
    CSS3中的弹性布局——"em"的用法
    Sublime Text3快捷键实用总结
    学习笔记——关于HTML(含HTML5)的块级元素和行级(内联)元素总结
    JavaScript中的伪数组理解
    深入理解浏览器兼容性模式
    javascript 中使用instanceof需要注意的一点
    用人工智能学习,凡亿推出PCB问题解答智能搜索机器人:pcb助手
    Altium中坐标的导出及利用坐标快速布局
    Altium中Logo的导入方法及大小调整
  • 原文地址:https://www.cnblogs.com/chenhaiming/p/9915287.html
Copyright © 2011-2022 走看看