I have simple producer, consumer problem. While producer thread adding 10$ to global money variable, consumer thread will spend money. But there is one condition that money cannot be under 0. The example code given below:
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()
I saw many examples and they are using while money < 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 ?
The reason for using a
whileloop is hinted at in the documentation:If you think about your code with an
if-condition:... it is possible (at least as far as the implementation of the condition variable is concerned) that
conditiongets lockedmoneyis smaller than0condition.wait(); the lock is unlocked and "something" happens elsewherecondition.conditionand executes, modifyingmoney, then unlockscondition.wait()after acquiring the lockWhile your code in particular may not be susceptible to this problem, it is generally good code hygiene // muscle memory to design your code in such a way that it does not suffer from the problem described above: While
.wait()executes, your thread might get notified, but the condition you are waiting for is no longer true by the timewait()returns.The
while-loop makes sure that if the condition became true and untrue while the lock was released, we simple try again.