Fizz Buzz Multithreaded
MediumUpdated: Aug 2, 2025
Practice on:
Problem
You have the four functions:
printFizzthat prints the word"fizz"to the console,printBuzzthat prints the word"buzz"to the console,printFizzBuzzthat prints the word"fizzbuzz"to the console, andprintNumberthat prints a given integer to the console.
You are given an instance of the class FizzBuzz that has four functions:
fizz, buzz, fizzbuzz and number. The same instance of FizzBuzz will be passed to four different threads:
- Thread A: calls
fizz()that should output the word"fizz". - Thread B: calls
buzz()that should output the word"buzz". - Thread C: calls
fizzbuzz()that should output the word"fizzbuzz". - Thread D: calls
number()that should only output the integers.
Modify the given class to output the series [1, 2, "fizz", 4, "buzz", ...]
where the ith token (1-indexed) of the series is:
"fizzbuzz"ifiis divisible by3and5,"fizz"ifiis divisible by3and not5,"buzz"ifiis divisible by5and not3, oriifiis not divisible by3or5.
Implement the FizzBuzz class:
FizzBuzz(int n)Initializes the object with the numbernthat represents the length of the sequence that should be printed.void fizz(printFizz)CallsprintFizzto output"fizz".void buzz(printBuzz)CallsprintBuzzto output"buzz".void fizzbuzz(printFizzBuzz)CallsprintFizzBuzzto output"fizzbuzz".void number(printNumber)Callsprintnumberto output the numbers.
Examples
Example 1
Input: n = 15
Output: [1,2,"fizz",4,"buzz","fizz",7,8,"fizz","buzz",11,"fizz",13,14,"fizzbuzz"]
Example 2
Input: n = 5
Output: [1,2,"fizz",4,"buzz"]
Constraints
1 <= n <= 50
Solution
Method 1 – Synchronization with Semaphores/Locks
Intuition
We need to coordinate four threads so that each prints the correct value in order. We use synchronization primitives (semaphores, locks, or condition variables) to ensure only the correct thread prints at each step.
Approach
- Use a shared counter to track the current number.
- Use synchronization (semaphores, locks, or condition variables) to ensure only the correct thread prints for each number.
- Each thread waits for its turn, prints if the condition matches, and notifies others.
- Repeat until n is reached.
Code
C++
#include <functional>
#include <mutex>
#include <condition_variable>
class FizzBuzz {
int n, curr = 1;
std::mutex mtx;
std::condition_variable cv;
public:
FizzBuzz(int n) : n(n) {}
void fizz(function<void()> printFizz) {
while (true) {
std::unique_lock<std::mutex> lk(mtx);
cv.wait(lk, [&]{ return curr > n || (curr % 3 == 0 && curr % 5 != 0); });
if (curr > n) break;
printFizz();
curr++;
cv.notify_all();
}
}
void buzz(function<void()> printBuzz) {
while (true) {
std::unique_lock<std::mutex> lk(mtx);
cv.wait(lk, [&]{ return curr > n || (curr % 5 == 0 && curr % 3 != 0); });
if (curr > n) break;
printBuzz();
curr++;
cv.notify_all();
}
}
void fizzbuzz(function<void()> printFizzBuzz) {
while (true) {
std::unique_lock<std::mutex> lk(mtx);
cv.wait(lk, [&]{ return curr > n || (curr % 15 == 0); });
if (curr > n) break;
printFizzBuzz();
curr++;
cv.notify_all();
}
}
void number(function<void(int)> printNumber) {
while (true) {
std::unique_lock<std::mutex> lk(mtx);
cv.wait(lk, [&]{ return curr > n || (curr % 3 != 0 && curr % 5 != 0); });
if (curr > n) break;
printNumber(curr);
curr++;
cv.notify_all();
}
}
};
Java
import java.util.concurrent.Semaphore;
class FizzBuzz {
private int n, curr = 1;
private final Semaphore fizz = new Semaphore(0), buzz = new Semaphore(0), fizzbuzz = new Semaphore(0), number = new Semaphore(1);
public FizzBuzz(int n) { this.n = n; }
public void fizz(Runnable printFizz) throws InterruptedException {
while (true) {
fizz.acquire();
if (curr > n) break;
printFizz.run();
curr++;
releaseNext();
}
}
public void buzz(Runnable printBuzz) throws InterruptedException {
while (true) {
buzz.acquire();
if (curr > n) break;
printBuzz.run();
curr++;
releaseNext();
}
}
public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
while (true) {
fizzbuzz.acquire();
if (curr > n) break;
printFizzBuzz.run();
curr++;
releaseNext();
}
}
public void number(IntConsumer printNumber) throws InterruptedException {
while (true) {
number.acquire();
if (curr > n) break;
printNumber.accept(curr);
curr++;
releaseNext();
}
}
private void releaseNext() {
if (curr > n) {
fizz.release(); buzz.release(); fizzbuzz.release(); number.release();
} else if (curr % 15 == 0) fizzbuzz.release();
else if (curr % 3 == 0) fizz.release();
else if (curr % 5 == 0) buzz.release();
else number.release();
}
}
Python
from threading import Lock, Condition
class FizzBuzz:
def __init__(self, n: int):
self.n = n
self.curr = 1
self.lock = Lock()
self.cv = Condition(self.lock)
def fizz(self, printFizz):
while True:
with self.cv:
while self.curr <= self.n and (self.curr % 3 != 0 or self.curr % 5 == 0):
self.cv.wait()
if self.curr > self.n:
self.cv.notify_all()
break
printFizz()
self.curr += 1
self.cv.notify_all()
def buzz(self, printBuzz):
while True:
with self.cv:
while self.curr <= self.n and (self.curr % 5 != 0 or self.curr % 3 == 0):
self.cv.wait()
if self.curr > self.n:
self.cv.notify_all()
break
printBuzz()
self.curr += 1
self.cv.notify_all()
def fizzbuzz(self, printFizzBuzz):
while True:
with self.cv:
while self.curr <= self.n and (self.curr % 15 != 0):
self.cv.wait()
if self.curr > self.n:
self.cv.notify_all()
break
printFizzBuzz()
self.curr += 1
self.cv.notify_all()
def number(self, printNumber):
while True:
with self.cv:
while self.curr <= self.n and (self.curr % 3 == 0 or self.curr % 5 == 0):
self.cv.wait()
if self.curr > self.n:
self.cv.notify_all()
break
printNumber(self.curr)
self.curr += 1
self.cv.notify_all()
Complexity
- ⏰ Time complexity:
O(n), each number is printed once. - 🧺 Space complexity:
O(1), only a few variables and synchronization primitives are used.