Python 线程 - "condition.wait" 和 "condition.notifyAll" 如何工作

5 投票
2 回答
17854 浏览
提问于 2025-04-16 04:17

我有以下的“消费者”代码:

    ....

    while 1:

        time.sleep(self.sleeptime)

        cond.acquire() #acquire the lock
        print currentThread(), "lock acquired"

        while itemq.isEmpty():
            cond.wait()

        itemq.consume()
        print currentThread(),"Consumed One Item"
        cond.release()

还有以下的生产者代码:

....     
while 1 :


           cond.acquire() #acquire the lock
           print currentThread(), "lock acquired"
           print currentThread(),"Produced One Item"
           itemq.produce()
           cond.notifyAll()
           cond.release()

           time.sleep(self.sleeptime)

我在运行这个程序时,有1个生产者和2个消费者。我不知道会得到什么结果。生产者调用了“notifyAll()”,所以我期待两个消费者都会从他们的“等待”中醒来。确实,我看到两个消费者都获得了锁,但只有第一个获得锁的消费者实际上得到了消费的机会。有人能告诉我“wait”命令是怎么工作的吗?如果两个线程都收到了“notifyAll”,为什么只有一个能消费呢?

谢谢,

Li

2 个回答

4

我觉得文档写得很清楚:

wait() 方法会释放锁,然后会阻塞,直到另一个线程通过 notify() 或 notifyAll() 方法唤醒它。一旦被唤醒,它会重新获取锁并返回。你也可以设置一个超时时间。

还有

注意:notify() 和 notifyAll() 方法不会释放锁;这意味着被唤醒的线程不会立刻从它们的 wait() 调用中返回,而是要等到调用 notify() 或 notifyAll() 的线程最终释放锁后,才能返回。

当然,任何时候只有一个线程可以拥有这个锁:这就是设置锁的核心目的!

换句话说,notifyAll 会把所有等待的线程变成准备运行的状态,实际上它们都在等待重新获取锁,以便继续执行:一旦发出通知的线程释放了锁,一个等待获取锁的线程就会获得它(其他线程如果还有的话,当然会继续等待锁被释放,这样在任何时候只有一个线程拥有锁)。

1

关键在于等待的循环:

while itemq.isEmpty():
        cond.wait()

cond.wait() 的实现大概是这样的(仅作示例):

def wait():
    cond.release()
    wait for notify
    cond.aquire()

因为有锁的存在,所以一次只有一个消费者可以退出“等待”这个函数。第一个退出的消费者发现 itemq.isEmpty() == false,然后就去消费这个物品。消费完后,他们再重新进入等待函数,并释放锁。

第二个消费者退出后,发现 itemq.isEmpty() == true,又立刻重新进入等待状态。

撰写回答