【问题标题】:python threads - how do "condition.wait" and "condition.notifyAll" workpython线程-“condition.wait”和“condition.notifyAll”如何工作
【发布时间】:2011-04-13 20:35:58
【问题描述】:

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

    ....

    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()”,所以我希望两个消费者都能从他们的“等待”中醒来。我看到确实两个消费者都获得了锁,但只有第一个获得锁的人才能真正使用该项目。有人可以告诉我“等待”命令是如何工作的吗?如果两个线程都得到了“notifyAll”,那怎么只有一个线程可以消费呢?

谢谢, 李

【问题讨论】:

  • 提示:您应该接受更多答案以提高获得答案的机会。
  • 我什至不知道有这种可能性:)
  • 感谢上帝,它是可逆的。我以为我会被永远谴责:)
  • 从来不明白这在 Python 中是如何工作的。如果在release()之前通知(),锁仍然被占用,你唤醒线程并且只有在释放条件的线程保持控制调用释放的情况下,任何在释放之前获得控制的唤醒线程都会进入睡眠状态在 notify() 之后立即。看起来 Python 中的原子性概念是相当“相对”的。

标签: python multithreading conditional-statements wait


【解决方案1】:

我觉得the docs很清楚:

wait() 方法释放锁, 然后阻塞直到它被唤醒 通过 notify() 或 notifyAll() 调用 相同的条件变量在另一个 线。唤醒后,它会重新获得 锁定并返回。也是 可以指定超时。

注意:notify() 和 notifyAll() 方法不释放锁;这 表示线程或线程 醒来不会从他们的 wait() 立即调用,但仅在 调用 notify() 的线程或 notifyAll() 最终放弃 锁的所有权。锁的所有权。

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

所以,IOW,notifyAll 将所有等待的线程置于准备运行状态,并且本质上都在等待再次获取锁以便它们可以继续:一旦通知器释放锁,一个 等待获得该锁的线程确实获得了它(其他线程,如果有的话,当然会继续等待再次释放锁,因此在任何给定时间只有一个线程拥有锁)。

【讨论】:

  • 谢谢 :) 我注意到第一个获得锁的人获胜。它是作为队列实现的还是什么?
  • @user,实现细节(未记录在案,并且可能出于任何原因或无原因随时更改)。如果您对特定版本感到好奇,请查看 Python 源代码,例如这里:xmpp.org/rfcs/rfc3921.html#sub 第 150 行及以下(包括用于获取/恢复和释放/保存的内部例程)。
  • 谢谢:) 我想我不明白,如果一个线程没有赢得锁,它会等待另一个 notify()...我以为一旦他被唤醒,他只会等待锁,不会等待另一个 notify()...
  • @AlexMartelli 你的意思是链接到 XMPP rfc 吗?我发现the actual python source code 读起来更有趣;)
【解决方案2】:

关键在等待的循环中:

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

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

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

因此,由于锁定,一次只有一个消费者退出“等待”功能。第一个退出等待函数的消费者检测到 itemq.isEmpty() == false 并继续消费该项目。然后他们重新进入等待函数并释放锁。

第二个消费者退出,再次检测到 itemq.isEmpty() == true,并立即重新进入 wait()。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多