Two producer threads split a list of items between them and push each item onto a shared queue. Three consumer threads pull items off the queue and add them to a running total. Print the final total.
Why this is gradable. Concurrent code can legitimately produce different interleavings on every run, so this practice bank only includes problems whose correctness reduces to one deterministic final value or invariant — never a specific thread ordering. If your solution is correct, it will print the exact same output on every run, no matter how the scheduler interleaves your threads. Every item is produced and consumed exactly once, so the sum of all items is fixed no matter which consumer happens to grab which item, or in what order.
Example
Input: 1 2 3 ... 100 (the integers 1 through 100)
Output: 5050
Why this needs a real queue, not shared state
Producers and consumers run at different, unpredictable speeds. A thread-safe queue (like Python's queue.Queue, or BlockingQueue in Java) handles the handoff for you: put/get are already synchronized, and consumers can block until an item is available instead of busy-waiting in a loop.
Approach
Split the item list across the producer threads; each producer pushes its share onto the shared queue.
Each consumer loops, pulling items off the queue and adding them to the total under a lock (the queue makes the handoff safe, but the shared total += item still needs its own lock).
Consumers need a way to know when to stop — e.g. a short get timeout once producers are known to be done, or sentinel "stop" values pushed after production finishes.
Walkthrough
python
1def producer(chunk):
2 for item in chunk:
3 q.put(item)
45def consumer():
6 global total
7 while True:
8 item = q.get()
9 if item is None:
10 break
11 with lock:
12 total += item
Line 1: space-separated integers (the items to sum)
Print the total.
Not solved yet
Ctrl+Enter
Editor
import threading, queue
items = list(map(int, input().split()))
q = queue.Queue()
total = 0
lock = threading.Lock()
defproducer(chunk):
for item in chunk:
q.put(item)
defconsumer():
global total
# TODO: pull items off q until it's drained, adding each to total under lockpass
n_producers = 2
chunk_size = (len(items) + n_producers - 1) // n_producers
chunks = [items[i:i + chunk_size] for i inrange(0, len(items), chunk_size)]
producers = [threading.Thread(target=producer, args=(c,)) for c in chunks]
consumers = [threading.Thread(target=consumer) for _ inrange(3)]
for p in producers:
p.start()
for p in producers:
p.join()
for c in consumers:
c.start()
for c in consumers:
c.join()
print(total)
Input (stdin)
Output
Run your code to see output here.
Isolated sandbox · not executed on your devicePowered by Judge0 CE (free, self-hosted). Runs in an isolated sandbox — not on your device.
Editor
import threading, queue
items = list(map(int, input().split()))
q = queue.Queue()
total = 0
lock = threading.Lock()
defproducer(chunk):
for item in chunk:
q.put(item)
defconsumer():
global total
# TODO: pull items off q until it's drained, adding each to total under lockpass
n_producers = 2
chunk_size = (len(items) + n_producers - 1) // n_producers
chunks = [items[i:i + chunk_size] for i inrange(0, len(items), chunk_size)]
producers = [threading.Thread(target=producer, args=(c,)) for c in chunks]
consumers = [threading.Thread(target=consumer) for _ inrange(3)]
for p in producers:
p.start()
for p in producers:
p.join()
for c in consumers:
c.start()
for c in consumers:
c.join()
print(total)
Input (stdin)
Output
Run your code to see output here.
Isolated sandbox · not executed on your devicePowered by Judge0 CE (free, self-hosted). Runs in an isolated sandbox — not on your device.