Problem 8 ZeroEvenOdd Multithreading Problem
Overview
In the ZeroEvenOdd problem, we aim to print a sequence in the format "01020304...". The challenge is that we have three different threads responsible for printing parts of this sequence: one prints zeros, one prints even numbers, and one prints odd numbers. Proper synchronization between these threads is crucial to ensure the sequence is printed correctly and without race conditions. Our task is to structure and synchronize the threads to print this sequence up to 2n collaboratively.
Step-by-step Algorithm
-
Initialize
- Start with the first number (0).
- Set up synchronization tools (locks, conditions, etc.).
-
Thread A (Zero Printer)
- Responsible for printing zeros.
-
Thread B (Even Number Printer)
- Prints even numbers in sequence.
-
Thread C (Odd Number Printer)
- Prints odd numbers in sequence.
-
Synchronization
- Ensure Thread A runs first, followed by either Thread B or Thread C based on whether the next number is even or odd.
-
Wrap-up
- Continue until the sequence length reaches
2n.
- Continue until the sequence length reaches
Algorithm Walkthrough
Assume n = 2. Our sequence should be "0102".
- Initialization:
- Set
n = 2. - Initialize
counter = 1.
- Set
- Zero Printing (
zero()function):- Print "0" because it's the starting character of the sequence.
- Odd Printing (
odd()function):- Since
counteris 1 (odd), this thread prints "1". - Increment
counterto 2. - Signal to the Zero thread by unlocking
zero_lock.
- Since
- Zero Printing (
zero()function):- Print "0" following the odd number.
- Even Printing (
even()function):- With
counterat 2 (even), this thread prints "2". - Signal the end of the sequence as
counternow equalsn.
- With
Synchronization Explained
- Zero Thread: No lock initially. Prints "0" and signals the Odd thread if the
counteris odd, or the Even thread ifcounteris even, by unlocking the respective lock. - Odd Thread: Initially locked. Waits for the Zero thread to signal. When unlocked, prints the odd number, increments
counter, and signals back to the Zero thread by unlockingzero_lock. - Even Thread: Initially locked. Waits for the Zero thread to signal after an odd number has been printed. When unlocked, prints the even number and signals back to the Zero thread.





import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Solution {
// Declare instance variables that are essential for our solution
private int n; // The number up to which we need to print
private int counter = 1; // Counter to keep track of the current number being printed
// Use ReentrantLock for synchronization as it's more flexible than synchronized methods or blocks
private final Lock lock = new ReentrantLock();
// Conditions are used to coordinate threads. Here, we declare three conditions:
// one for zeros, one for even numbers, and one for odd numbers
private final Condition zeroCondition = lock.newCondition();
private final Condition evenCondition = lock.newCondition();
private final Condition oddCondition = lock.newCondition();
// Flags to keep track of whose turn it is to print
private boolean zeroTurn = true; // We start with zero
private boolean oddTurn = true; // We start with odd after zero, before even
// Constructor: Initializes the object and sets the value of n
public Solution(int n) {
this.n = n;
}
// Method for thread A to print zeros
public void zero() throws InterruptedException {
for (int i = 0; i < n; i++) {
lock.lock(); // Acquire the lock before checking conditions and printing
try {
// Keep the thread in a waiting state while it's not zero's turn to print
while (!zeroTurn) {
zeroCondition.await();
}
printNumber(0); // Once out of the wait state, print zero
zeroTurn = false; // Switch the flag since zero has been printed
// Depending on whether the next number is odd or even, signal the appropriate thread to take over
if (oddTurn) {
oddCondition.signal();
} else {
evenCondition.signal();
}
} finally {
lock.unlock(); // Always release the lock in the finally block to ensure it's released under all circumstances
}
}
}
// Method for thread B to print even numbers
public void even() throws InterruptedException {
for (int i = 2; i <= n; i += 2) {
lock.lock();
try {
// The even thread waits if it's zero's turn to print or if the current number is odd
while (zeroTurn || oddTurn) {
evenCondition.await();
}
printNumber(i); // Print the even number
zeroTurn = true; // Switch the turn back to zero
oddTurn = true; // After an even, the next number will be odd
zeroCondition.signal(); // Signal the zero thread to take over
} finally {
lock.unlock();
}
}
}
// Method for thread C to print odd numbers
public void odd() throws InterruptedException {
for (int i = 1; i <= n; i += 2) {
lock.lock();
try {
// The odd thread waits if it's zero's turn or if the current number is even
while (zeroTurn || !oddTurn) {
oddCondition.await();
}
printNumber(i); // Print the odd number
zeroTurn = true; // Switch the turn back to zero
oddTurn = false; // After an odd, the next number will be even
zeroCondition.signal(); // Signal the zero thread to take over
} finally {
lock.unlock();
}
}
}
// Utility method to actually output the number to the console
public void printNumber(int num) {
System.out.print(num);
}
// Main method to demonstrate the solution
public static void main(String[] args) {
// Create an instance of the ZeroEvenOdd class with a value of 5
Solution zeo = new Solution(5);
// Create three threads: one for zero, one for even numbers, and one for odd numbers
Thread t1 = new Thread(() -> {
try {
zeo.zero();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
try {
zeo.even();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t3 = new Thread(() -> {
try {
zeo.odd();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// Start all the threads
t1.start();
t2.start();
t3.start();
}
}
🤖 Don't fully get this? Learn it with Claude
Stuck on Problem 8 ZeroEvenOdd Multithreading Problem? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Progressively stronger hints — you still solve it.
I'm working on the problem **Problem 8 ZeroEvenOdd 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.
See the technique, not just code.
Explain the optimal approach to **Problem 8 ZeroEvenOdd 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.
Catch bugs, edge cases, sub-optimality.
I'll paste my solution to **Problem 8 ZeroEvenOdd 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.
Lock in recognition with look-alikes.
Give me 2 problems that use the SAME underlying pattern as **Problem 8 ZeroEvenOdd 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.