Python Lock 死锁问题

本文通过实例分析了Python中死锁的发生条件,并展示了如何通过调整代码避免死锁。在1.2.1部分,一个简单的银行转账模拟演示了死锁的产生,当从_和to线程独立进行解锁和上锁操作时会出现死锁。而在1.2.2节,给出了正确的代码实现,避免了死锁,使得转账操作成功完成。

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

1.1死锁发生的必要条件
在这里插入图片描述
在这里插入图片描述1.2.1死锁例子 简单模拟银行转账

"""
    银行转账
"""

from time import sleep
from threading import Thread,Lock

# 账户类
class Account:
    def __init__(self, _id, balance, lock):
        self.id = _id   # 用户
        self.balance = balance  # 存款
        self.lock = lock    # 锁

    # 取钱
    def withdraw(self, amount):
        self.balance -= -amount

    # 存钱
    def deposit(self, amount):
        self.balance += amount

    # 查看余额
    def get_balance(self):
        return self.balance

# 产生两个账户
Tom = Account('Tom', 5000, Lock())
Alex = Account('Alex', 8000, Lock())

# 转账过程
def transfer(from_, to, amount):
    if from_.lock.acquire():    # 锁住自己的账户
        from_.withdraw(amount)
        sleep(0.5)
        if to.lock.acquire():   #
### 解决Python多线程或多进程中的死锁问题 #### 死锁产生的原因 当多个线程或进程试图获取相同的资源时,如果它们按照不同的顺序请求这些资源,则可能会发生死锁。例如,在两个线程分别持有不同的情况下尝试获得对方持有的另一个,这将导致两者无限期等待。 为了防止这种情况的发生,可以采取一些预防措施来确保不会形成循环等待条件[^3]。 #### 预防策略之一:按固定顺序加 一种简单而有效的方式就是规定所有线程都必须遵循固定的定顺序。这意味着如果有多个互斥量需要被同一个线程占有,则该线程应该总是先去申请编号较小的那个互斥量再依次向上直到最大的那个。这样做能够打破循环等待链从而避免死锁现象的发生。 ```python import threading x_lock = threading.Lock() y_lock = threading.Lock() def thread_1(): while True: with x_lock: # Always acquire locks in a fixed order (e.g., x before y) with y_lock: print('Thread-1') def thread_2(): while True: with x_lock: # Ensure the same lock acquisition order as Thread-1 with y_lock: print('Thread-2') ``` #### 使用超时机制释放未成功获取 另一种方法是在尝试获取某个特定资源之前设置一个合理的超时期限;一旦超过这个时间仍然无法得到所需资源就主动放弃当前操作并回滚已经完成的部分工作以便让其他竞争者有机会继续执行下去。这种方法虽然不能完全消除死锁的可能性但是可以在一定程度上减少其发生的概率[^2]。 ```python try: if not x_lock.acquire(timeout=5): # Try to get 'x' within 5 seconds. raise Exception("Failed to acquire x_lock.") try: if not y_lock.acquire(timeout=5): # Then try to get 'y'. raise Exception("Failed to acquire y_lock after getting x_lock.") # Critical section here... finally: y_lock.release() # Make sure we release both locks even on error finally: x_lock.release() ``` #### 尽可能简化临界区逻辑 保持临界区内代码尽可能短小精悍有助于降低因长时间占用共享资源而导致潜在冲突的机会。因此建议开发者们尽量缩短进入和退出之间的时间间隔以提高系统的整体性能以及稳定性[^1].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值