Python学习笔记5-死锁

在Python中,死锁主要发生在多线程或多进程程序中,特别是在涉及到锁(如threading.Lock)的情况。死锁在这些环境下的发生与其他语言类似,主要原因是多个线程或进程相互等待,导致系统无法继续执行。

死锁的示例

假设有两个线程(T1和T2)和两个锁(Lock1和Lock2)。如果T1先获取Lock1,然后尝试获取Lock2,而T2先获取Lock2,然后尝试获取Lock1,就可能导致死锁,因为两个线程相互等待对方释放锁。

示例代码
import threading

# 创建两个锁
lock1 = threading.Lock()
lock2 = threading.Lock()

def thread1_task():
    with lock1:
        print("Thread 1 acquired lock1")
        # 模拟线程1的工作
        threading.Event().wait(1)
        print("Thread 1 attempting to acquire lock2")
        with lock2:
            print("Thread 1 acquired lock2")

def thread2_task():
    with lock2:
        print("Thread 2 acquired lock2")
        # 模拟线程2的工作
        threading.Event().wait(1)
        print("Thread 2 attempting to acquire lock1")
        with lock1:
            print("Thread 2 acquired lock1")

# 启动两个线程
thread1 = threading.Thread(target=thread1_task)
thread2 = threading.Thread(target=thread2_task)

thread1.start()
thread2.start()

thread1.join()
thread2.join()

在这个示例中,thread1_taskthread2_task两个线程尝试获取锁的顺序不同,可能导致死锁。

避免死锁的技巧

  1. 避免锁的交叉

    • 尽量避免多个线程或进程之间的锁竞争,特别是避免锁的交叉持有。确保所有线程按相同的顺序获取锁。
  2. 使用threading.Lock时保持简短的临界区

    • 尽量将持有锁的时间控制在最小范围内,避免在锁持有期间执行时间较长的操作。
  3. 使用with语句

    • 使用with语句来管理锁,这样可以确保在代码块执行完后,锁会自动释放,减少忘记释放锁的风险。
  4. 使用超时

    • 使用Lock.acquire(timeout)方法来设置锁的获取超时时间。如果线程在指定时间内无法获取锁,则放弃请求。这样可以避免因等待过长时间而导致死锁。
    def thread1_task():
        acquired = lock1.acquire(timeout=2)
        if acquired:
            print("Thread 1 acquired lock1")
            threading.Event().wait(1)
            print("Thread 1 attempting to acquire lock2")
            acquired = lock2.acquire(timeout=2)
            if acquired:
                print("Thread 1 acquired lock2")
                lock2.release()
            lock1.release()
        else:
            print("Thread 1 could not acquire lock1")
    
    def thread2_task():
        acquired = lock2.acquire(timeout=2)
        if acquired:
            print("Thread 2 acquired lock2")
            threading.Event().wait(1)
            print("Thread 2 attempting to acquire lock1")
            acquired = lock1.acquire(timeout=2)
            if acquired:
                print("Thread 2 acquired lock1")
                lock1.release()
            lock2.release()
        else:
            print("Thread 2 could not acquire lock2")
    
  5. 使用死锁检测工具

    • 可以利用Python的一些库和工具(如threading模块的Thread对象的is_alive()方法等)来帮助检测可能的死锁情境。

死锁的管理和避免是多线程编程中的关键部分,理解其发生机制并采取适当的措施可以帮助你编写更健壮的并发程序。

  • 21
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值