I am using multiprocessing.Queue to implement classic producer-consumer pattern. To let consumers know all the tasks are done. I use a special None as sentinel. And I use Lock and Value(counter) to judge if current process is the last producer. If it is the last producer, it will put as many None as the number of consumers to the queue.
``` def producer(queue, lock, running_counters, num_consumers): while task_not_done: result = do something queue.put(result) # I am done with lock: running_counters.value -= 1 if running_counters.value == 0: # last one, put sentinel Nones for _ in range(num_consumers): queue.put(None) def consumer(queue): while True: data = queue.get() if data is None: break do something with data def main(): queue = mp.Queue(maxsize=1_000_000) running_counters = mp.Value('i', NUM_PRODUCER) lock = mp.Lock() producers = [] for _ in range(NUM_PRODUCER): p = mp.Process(target=producer, args=(queue, lock, running_counters, NUM_CONSUMER)) p.start() producers.append(p) consumers = [] for _ in range(NUM_CONSUMER): p = mp.Process(target=consumer, args=(queue,)) p.start() consumers.append(p) [p.join() for p in producers] [p.join() for p in consumers] ``` I run this code in one machine, it works. But in another it deadlocks. when it deadlocks, I find that even all the consumers finished, the queue is still not empty. So the producers can't finish. I am very confused about this. Why use lock has synchronization problem. It seems when the last producer put None to queue, other producers still can put normal data to queue. I am not familiar with python multiprocessing. And unlike java/c++, I can't find clear documents about python memory model which define happens-before or fence or related topic. I know python multiprocessing is not multithreads which all threads share the memory space of the same process. Some web blogs say mp.Queue.put() will use background thread to send message. Maybe when last producer put None to the queue(it's fast), other producers' put is still running? If it's true, how I can know all background sending is done? -- https://mail.python.org/mailman3//lists/python-list.python.org