Python多线程实现奇偶生成报错:RuntimeError: cannot notify on un-acquired lock
问题分析与解决
首先,你遇到的RuntimeError: cannot notify on un-acquired lock是因为在evenNumbers方法中,调用notify()之前就已经释放了Condition的锁。当你执行self.c.release()后,当前线程就不再持有这个锁了,后续的self.c.notify()自然会抛出异常。
另外,你的代码还有两个逻辑问题:
Odd类的oddNumbers方法只执行一次打印,没有循环生成所有奇数- 没有使用
wait()来实现线程间的交替等待,两个线程会出现执行顺序混乱的问题
下面是修正后的完整代码,我会标注关键修改点:
from threading import * from time import sleep class Even: def __init__(self): self.c = Condition() self.num = 0 # 初始化num,避免Odd线程读取时出现未定义问题 def evenNumbers(self): self.c.acquire() for i in range(0, 101, 2): print("Even : ", i) self.num = i sleep(1.) self.c.notify() # 唤醒等待的Odd线程 if i != 100: # 最后一次循环不需要等待,避免线程挂起 self.c.wait() # 释放锁,等待Odd线程的通知 self.c.release() # 循环结束后释放锁 class Odd: def __init__(self, even): self.even = even def oddNumbers(self): self.even.c.acquire() for _ in range(1, 100, 2): # 循环生成1-99的奇数 self.even.c.wait() # 先等待Even线程打印偶数 print("Odd : ", self.even.num + 1) sleep(1.) self.even.c.notify() # 唤醒Even线程继续打印下一个偶数 self.even.c.release() tEven = Even() tOdd = Odd(tEven) t1 = Thread(target=tEven.evenNumbers) t2 = Thread(target=tOdd.oddNumbers) t1.start() t2.start()
关键修改说明:
- 锁的生命周期修正:在
evenNumbers中,将release()移到循环结束后,确保notify()和wait()都在锁持有状态下执行 - 添加
wait()实现交替:两个线程通过wait()释放锁并等待对方的notify(),实现严格的奇偶交替打印 - 初始化
num属性:避免Odd线程首次读取时出现属性未定义的问题 - Odd线程添加循环:让Odd线程能生成所有1-99的奇数
- 最后一次循环跳过wait:Even线程打印最后一个偶数(100)后,不需要再等待,避免线程一直挂起
运行修正后的代码,就能看到两个线程交替打印偶数和奇数了。
内容的提问来源于stack exchange,提问作者Phys
相关产品推荐
相关产品推荐

