While creating a simple consumer-producer thread structure using locks in Python I encountered some issues which caused the program to create unexpected output.
import threading
from time import sleep
import random
class AI:
def __init__(self):
self.a = None
self.mainLock = threading.Lock()
threading.Thread(target=self.producer,daemon=True).start()
threading.Thread(target=self.consumer,daemon=True).start()
def producer(self):
while True:
self.mainLock.acquire()
sleep(1)
temp = random.randint(-1,10)
print(f"Produced {temp}")
self.a = temp
self.mainLock.release()
def consumer(self):
while True:
self.mainLock.acquire()
if(self.a and self.a>0):
sleep(1.5)
print(f"Consumed {self.a}")
self.a = None
self.mainLock.release()
a = AI()
input()
Output -
Produced 0
Produced 8
Produced 9
Produced 1
Produced 9
Produced 10
Produced 5
Produced 1
Which is clearly not what was expected here. The expected output would have contained consumer after producer. But if I add any statement after releasing the lock inside the producer then the code runs fine as it was expected to run.
Code -
import threading
from time import sleep
import random
class AI:
def __init__(self):
self.a = None
self.mainLock = threading.Lock()
threading.Thread(target=self.producer,daemon=True).start()
threading.Thread(target=self.consumer,daemon=True).start()
def producer(self):
while True:
self.mainLock.acquire()
sleep(1)
temp = random.randint(-1,10)
print(f"Produced {temp}")
self.a = temp
self.mainLock.release()
## = Newly added line
########################
print("released")
########################
def consumer(self):
while True:
self.mainLock.acquire()
if(self.a and self.a>0):
sleep(1.5)
print(f"Consumed {self.a}")
self.a = None
self.mainLock.release()
a = AI()
input()
Output -
Produced 10
released
Consumed 10
Produced 7
released
Consumed 7
Produced 2
released
Consumed 2
Even if I replace the print statement with a sleep statement then also the code works irrespective of how small the sleep duration is it still works fine.
Example -
sleep(0.0000000000000000000000000000000000000000000000000000000000000000000000001)
Why is it happening? And how was the code able the jump back from consumer to producer without any print or sleep after consumer's release without which the code was not able to jump from producer to consumer?