CMD Guide
HomeConcurrencyConcurrency Problems

Problem 7 FizzBuzz Multithreading Problem

Four threads, one ordered output — coordinated by a shared counter

Four threads each own one job: print the number, print "fizz" (n%3==0, not %5), "buzz" (n%5==0, not %3), or "fizzbuzz" (n%15==0). They must cooperate so the combined output is exactly 1 2 fizz 4 buzz fizz 7 … in order. The mechanism is a single shared counter current guarded by a lock + condition: each thread waits until current is a value that belongs to it, prints, advances the counter, and wakes the others. The earlier version was broken twice over — the method was named Solution() and printed the literal string "Solution" on multiples of 15, and the driver never joined its threads, so the program could exit before finishing.

Correct Java

import java.util.concurrent.locks.*;
import java.util.function.IntConsumer;

class FizzBuzz {
    private final int n;
    private int current = 1;
    private final Lock lock = new ReentrantLock();
    private final Condition cv = lock.newCondition();
    FizzBuzz(int n) { this.n = n; }

    private void run(java.util.function.IntPredicate mine, Runnable print) throws InterruptedException {
        while (true) {
            lock.lock();
            try {
                while (current <= n && !mine.test(current)) cv.await(); // not my turn
                if (current > n) return;                                // done
                print.run();
                current++;
                cv.signalAll();
            } finally { lock.unlock(); }
        }
    }
    public void fizz(Runnable p)     throws InterruptedException { run(i -> i%3==0 && i%5!=0, p); }
    public void buzz(Runnable p)     throws InterruptedException { run(i -> i%5==0 && i%3!=0, p); }
    public void fizzbuzz(Runnable p) throws InterruptedException { run(i -> i%15==0, p); }
    public void number(IntConsumer p) throws InterruptedException {
        while (true) {
            lock.lock();
            try {
                while (current <= n && (current%3==0 || current%5==0)) cv.await();
                if (current > n) return;
                p.accept(current);
                current++;
                cv.signalAll();
            } finally { lock.unlock(); }
        }
    }
}
// driver: start all four threads, then join EACH so main waits for completion.

Correct Go

Go expresses the same coordination with sync.Mutex + sync.Cond, and a sync.WaitGroup replaces the explicit joins.

type FizzBuzz struct{ n, cur int; mu sync.Mutex; cv *sync.Cond }
func (f *FizzBuzz) step(mine func(int) bool, print func(int)) {
    for {
        f.mu.Lock()
        for f.cur <= f.n && !mine(f.cur) { f.cv.Wait() }
        if f.cur > f.n { f.mu.Unlock(); return }
        print(f.cur); f.cur++; f.cv.Broadcast()
        f.mu.Unlock()
    }
}
// number: mine = func(i int) bool { return i%3!=0 && i%5!=0 }
// wg.Add(4); go each step; wg.Wait()

Worked schedule for n = 15 (who prints each i)

iPredicate trueThread that printsOutput token
1not ÷3, not ÷5number1
2numbernumber2
3÷3 onlyfizzfizz
4numbernumber4
5÷5 onlybuzzbuzz
6÷3 onlyfizzfizz
15÷3 and ÷5fizzbuzz onlyfizzbuzz

At i=15, fizz and buzz predicates must be false (they check ÷3-not-÷5 and ÷5-not-÷3). Only fizzbuzz matches; after it prints, current++ and signalAll let the others re-check and park until their next hit. Wrong exclusive predicates → double print or hang.

Pitfalls

When four threads are the wrong answer

This is a coordination exercise, not a throughput pattern. If you only need correct FizzBuzz output, a single sequential loop that switches on i%15 / i%3 / i%5 is simpler and strictly faster: the four threads here serialize almost entirely through the one lock — only one of them may act at each i — so you pay context switches and condition signalling to gain nothing. Put a number on it: the critical section is the entire per-i body (check predicate, print, advance, signal), so the serial fraction is ≈ 1. Amdahl's law then caps speedup at 1/(serial fraction) ≈ 1× no matter how many threads or cores you add — you have bought zero parallelism and spent an extra ~3 signalAll wake-and-recheck cycles per number (the three threads that were not whose turn it is each wake, re-test, and re-park). That is the honest crossover: the multithreaded version is strictly slower than the one-line sequential loop for every value of n, and is justified only as an exercise in condition-variable coordination. Defend the counter+condition design only when the constraint really is "four threads, each owning one predicate." One thing it is not a good fit for: four BlockingQueues of pre-routed tokens would just reintroduce a single sequencer deciding which queue to feed each step, which defeats the point of letting all four threads observe the shared counter themselves.

Takeaways


Re-authored for correctness for this guide (the prior version printed "Solution" and never joined its threads). Pattern: LeetCode 1195 "Fizz Buzz Multithreaded". See also: Condition Variables, Mutex Lock.

🔨 Practice this hands-on — Build Multithreaded FizzBuzz →
Attempt it from an empty file, break it to feel the failure, then defend it under pushback.
🤖 Don't fully get this? Learn it with Claude

Stuck on Problem 7 FizzBuzz Multithreading Problem? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🪜 Hint ladder (no spoilers)

Progressively stronger hints — you still solve it.

I'm working on the problem **Problem 7 FizzBuzz Multithreading Problem** (Concurrency). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🎨 Explain the approach visually

See the technique, not just code.

Explain the optimal approach to **Problem 7 FizzBuzz Multithreading Problem** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔍 Review my solution

Catch bugs, edge cases, sub-optimality.

I'll paste my solution to **Problem 7 FizzBuzz Multithreading Problem**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔁 Drill the pattern

Lock in recognition with look-alikes.

Give me 2 problems that use the SAME underlying pattern as **Problem 7 FizzBuzz Multithreading Problem**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes