为什么在条件变量中使用while控制而不是if控制来同步不同线程?

问题描述 投票:0回答:1

我有简单的生产者、消费者问题。当生产者线程向全局货币变量添加 10$ 时,消费者线程将花钱。但有一个条件,money 不能低于 0。示例代码如下:

from threading import Thread, Condition

condition = Condition()
money = 0

def producer():
    global money
    for _ in range(1000000):
        condition.acquire()
        money += 10
        condition.notify()
        condition.release()

def consumer():
    global money
    for _ in range(500000):
        condition.acquire()
        if money < 0:
        # while money < 0: why it's needed ? 
            condition.wait()
        money -= 20
        print("money in the bank after spend => ", money)
        condition.release()
        

if __name__ == "__main__":
 
    t1 = Thread(target=producer, args=())
    t2 = Thread(target=consumer, args=())

    t1.start()
    t2.start()

    t1.join()
    t2.join()

我看到很多例子,他们都在用 while 钱 < 20: instead of my if control and I am confused right there. When thread waits with condition.wait() simply it release the condition lock and when consumer consume 10$ then notify the producer thread, the producer function starts working with acquiring the condition lock first. So there is no make sense to use while loop over there. Because every time the thread notifies, first step the notified thread try to acquire the lock and rest of the code continues working as normal flow. So there is no need to use while loop to control money variable's instant change, it will control the money variable anyways if the program running as expected. Am I right ? Or am I missing some point ?

python multithreading python-multithreading condition-variable thread-synchronization
1个回答
0
投票

使用

while
循环的原因在文档中暗示:

While 循环检查应用程序的条件是必要的,因为 wait() 可以在任意长时间后返回,并且提示调用 notification() 的条件可能不再成立。

如果您考虑带有

if
条件的代码:

with condition:
    if money < 0:
        condition.wait()
    money -= 20

...有可能(至少就条件变量的实现而言)

  1. condition
    被锁定
  2. money
    小于
    0
  3. 我们
    condition.wait()
    ;锁被解锁,其他地方发生了“某事”
  4. “某事”通知所有正在等待的线程
    condition
  5. 其他一些线程获取
    condition
    上的锁并执行,修改
    money
    ,然后解锁
    condition
  6. 我们的线程在获取锁后从
    .wait()
    返回
  7. 虽然我们等待的条件在我们没有获取锁时已经变为真,但在我们没有获取锁时它也变得不真。我们收到有关情况“变化”的通知。但当我们抽出时间去检查它时,它就不再是真的了。

虽然您的代码可能不太容易受到此问题的影响,但通常来说,以不会遇到上述问题的方式设计代码是良好的代码卫生 // 肌肉记忆:当

.wait()
执行时,您的线程可能会收到通知,但当 wait()
 返回
时,您正在等待的条件不再为真。

while

循环确保如果在释放锁时条件变为真或不真,我们只需重试即可。

© www.soinside.com 2019 - 2024. All rights reserved.