多线程过桥的问题

本文通过Python的多线程实现了一个模拟过桥场景的问题,桥作为共享资源,南北两岸各有不同数量的人群等待过桥,每个行人由单独的线程控制,展示了如何在并发环境中管理共享资源。
题目:有一个南北向的桥,只能容纳一个人,现桥的两边分别有10人和12人,编制一个多线程序让这些人到达对岸,每个人用一个线程表示,桥为共享资源。在过桥的过程中显示谁在过桥及其走向。

import threading
import time
from collections import deque

class Person(threading.Thread):
def __init__(self, id, msg):
threading.Thread.__init__(self)
self.id = id
self.msg = msg
def run(self):
cross(self)
def cross(self):
print(str(self.id) + "\t" + self.msg)

class PersonPool(threading.Thread):
canCross = threading.RLock()
def __init__(self):
threading.Thread.__init__(self)
self.persons = deque([])
self.shutdown = False
def add(self, person):
self.persons.append(person)
def stop(self):
self.shutdown = True
def run(self):
self.waitForPerson()
def waitForPerson(self):
while self.shutdown == False:
PersonPool.canCross.acquire()
while len(self.persons) != 0:
person = self.persons.popleft()
person.cross()
time.sleep(1)
PersonPool.canCross.release()

if __name__ == "__main__":
nsPool = PersonPool()
snPool = PersonPool()

snPool.start()
nsPool.start()

for i in xrange(0, 10):
snPool.add(Person(i, "From North To South"))
for j in xrange(0, 12):
snPool.add(Person(j, "From South To North"))
<think>好的,用户现在问的是如何避免多线程中的死锁。之前他们问了竞态条件,所以我需要确保这次回答既相关又深入。用户可能是刚开始学习多线程编程,或者在实际开发中遇到了问题。需要明确死锁的四个必要条件,这样才能针对性地给出解决方法。 首先,我应该回顾死锁的定义,然后列举必要条件:互斥、持有并等待、不可抢占、循环等待。接下来,针对每个条件给出避免的方法。比如,破坏其中一个条件就能避免死锁。比如,资源一次性分配可以解决持有并等待的问题,或者按顺序申请资源来破坏循环等待。 可能用户需要实际例子,比如银行家算法或者代码示例。但用户之前的问题中有Python示例,所以可能期待类似的代码说明。比如,展示按顺序申请锁来避免循环等待。 还要考虑用户的实际应用场景,比如在开发中如何设计资源分配策略,或者使用超时机制。另外,用户可能想知道工具或库的支持,比如Java中的Lock类或者数据库事务的隔离级别。 需要注意避免使用太专业的术语,保持解释清晰易懂。同时,结合生活中的类比,比如两辆车过桥的例子,帮助理解死锁的发生和解决方法。 最后,总结预防措施,强调设计阶段的规划重要性,以及测试和监控的必要性。确保用户不仅知道理论,还能应用到实际开发中。</think>**多线程避免死锁的方法** 死锁(Deadlock)是多线程编程中因资源竞争导致的僵局:多个线程相互等待对方释放资源,导致程序无法继续执行。避免死锁的关键在于**破坏死锁的四个必要条件**(互斥、持有并等待、不可抢占、循环等待)。以下是常见策略: --- ### **1. 破坏“持有并等待”条件** - **资源一次性分配** 线程在运行前一次性申请所有所需资源,避免中途请求新资源。 ```python # 示例:通过一次性获取两把锁避免死锁 lock_A = threading.Lock() lock_B = threading.Lock() def thread_1(): with lock_A, lock_B: # 同时获取两把锁 # 执行操作 def thread_2(): with lock_A, lock_B: # 同上 # 执行操作 ``` **缺点**:可能导致资源浪费(资源未被立即使用)。 --- ### **2. 破坏“循环等待”条件** - **资源顺序化申请** 全局约定资源申请顺序,所有线程按固定顺序获取资源。 ```python # 示例:按固定顺序(A→B)申请锁 def thread_1(): with lock_A: with lock_B: # 执行操作 def thread_2(): with lock_A: # 先尝试获取 lock_A(与 thread_1 顺序一致) with lock_B: # 执行操作 ``` **关键**:若线程均按统一顺序申请资源,循环等待无法形成。 --- ### **3. 破坏“不可抢占”条件** - **允许资源抢占** 若线程请求资源失败,主动释放已持有资源,稍后重试。 ```java // Java 示例:使用 tryLock() 尝试获取锁,失败则释放 Lock lockA = new ReentrantLock(); Lock lockB = new ReentrantLock(); void threadTask() { while (true) { if (lockA.tryLock()) { try { if (lockB.tryLock()) { try { // 执行操作 break; } finally { lockB.unlock(); } } } finally { lockA.unlock(); } } // 短暂等待后重试 Thread.sleep(100); } } ``` **缺点**:频繁重试可能降低性能。 --- ### **4. 使用超时机制** - 为资源申请设置超时时间,超时后放弃并释放资源。 ```python # Python 示例:设置锁的超时时间 def thread_1(): if lock_A.acquire(timeout=2): try: if lock_B.acquire(timeout=2): try: # 执行操作 finally: lock_B.release() finally: lock_A.release() ``` --- ### **5. 死锁检测与恢复** - **工具监控**:通过算法(如银行家算法)或工具(如线程分析器)检测死锁。 - **强制终止**:发现死锁时,强制终止部分线程或回滚操作。 --- ### **实际开发中的建议** 1. **减少锁的粒度**:缩小临界区范围(如使用细粒度锁)。 2. **避免嵌套锁**:尽量不在持有锁时申请其他锁。 3. **使用高层抽象**:优先使用线程安全的数据结构(如 `Queue`)或异步编程模型。 --- ### **生活中的类比** 两辆车在狭窄的桥头相遇,均等待对方倒车让路(死锁)。解决方法: - 规定所有车辆必须从同一方向依次通过(破坏循环等待)。 - 若僵持不下,其中一辆车主动倒车退出(超时释放资源)。 通过合理设计资源分配策略,可有效避免多线程死锁问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值