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)
     
  • 相关阅读:
    eclipse中的TODO和FIXME
    使用mui框架后a标签无法跳转
    java.lang.OutOfMemoryError: Java heap space异常
    mysql中表触发器的简单使用
    编写第一个 Java 程序
    QDialog类exec()与show()的区别
    Qt中信号槽connect的多种类型
    2.3 UML活动图
    2.2 UML用例模型
    2.1 uml序言
  • 原文地址:https://www.cnblogs.com/chenhaiming/p/9915287.html
Copyright © 2011-2022 走看看