You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 14:33:13