PYTHON——多线程:死锁和递归锁(RLock)

本文深入探讨了在多线程环境下死锁现象的发生原因及其解决方案。通过具体代码实例,详细解析了死锁如何在两个线程争夺资源时发生,并介绍了Python中RLock(递归锁)的使用方法,展示了如何利用RLock避免死锁,确保线程安全。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、死锁现象

# 在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁,
# 因为系统判断这部分资源都正在使用,所有这两个线程在无外力作用下将一直等待下去。
# 下面是一个死锁的例子:
实例代码:
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)
 

 

转载于:https://www.cnblogs.com/chenhaiming/p/9915287.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值