I have implemented a producer/consumer functionality using threads in a given framework and
I'm pretty sure I did not cover all possible scenarios.
I made a small reproducible version. Lines ending with
# simulate the functionality of the framework.
In the original code the total number of products and consumers is not known until the end.
My goal is to wait in the producer thread until the consumer thread has finished the current product and vice versa. So the order should be:
- consumer boot (first or 2nd step)
- producer produce product #1 (first or 2nd step)
- consumer consume product #1
- producer produce product #2
- consumer consume product #2
until there is either no product or consumer left
This is a MRE of my code (with sleeps as placeholders), alter the value of
n to simulate more or less consumers:
import threading import time products = [1,2,3,4,5,None] # prodcnt = 0 # n = 5 # def produce(): #simulating incremental calculation of product while True: # global prodcnt # product = products[prodcnt] # prodcnt += 1 # print(" Producer: init product "+str(product)) if product == None: # global exhausted exhausted = True getProdEvent.set() print(" Producer: exhausted") return elif noConsumers: print(" Producer: no consumers left") return else: print(" Producer: waiting for permission to process "+str(product)) getConsumeEvent.wait() print(" Producer: Permission granted "+str(product)) time.sleep(0.01) print(" Producer: finished producing "+str(product)) getProdEvent.set() getConsumeEvent.clear() exhausted = False noConsumers = False step = 0 getProdEvent = threading.Event() getConsumeEvent = threading.Event() x = threading.Thread(target=produce) # x.start() # while not exhausted and not noConsumers: if step > 0: print("Consumer: wait for product #" +str(step)+"\n", end="") getProdEvent.clear() if not exhausted: getProdEvent.wait() else: print("Consumer: booting ... please wait") time.sleep(0.02) print("Consumer: finishing #"+str(step)) time.sleep(0.05) getConsumeEvent.set() if step >= n: # simulate no Consumers left print("Consumer: No consumers left") noConsumers = True getConsumeEvent.set() step +=1
Is there a more straight forward way to force them to wait for each other? Also I feel like my code could break easily.
The producer uses the value of
step so the command
step +=1 should run only if the producer is stuck in the line