Problem 13 Synchronization of Dual Threads
Overview
The "Synchronization of Dual Threads" problem is a classic demonstration of concurrent thread management. Given two threads, A and B, with the responsibilities of printing "foo" and "bar" respectively, the task is to ensure a synchronized output of "foobar" repetitively for a given 'n' times. This problem emphasizes the significance of thread synchronization in producing consistent and predictable results in concurrent systems.
Pseudocode
Initialize a semaphore or mutex called fooLock with a value of 1 Initialize a semaphore or mutex called barLock with a value of 0 Function printFoo(): for i from 1 to n do: Acquire fooLock Print "foo" Release barLock Function printBar(): for i from 1 to n do: Acquire barLock Print "bar" Release fooLock Main: Start Thread A -> Target: printFoo Start Thread B -> Target: printBar
Explanation
- We start by defining a
FooBarclass that has methodsfooandbarto print "foo" and "bar" respectively. - The synchronization is achieved using a mutex
mtxand two condition variablesfooPrintedandbarPrinted. - In the
foomethod, we ensure that "foo" is printed first. Once printed, it setsfooDoneto true and signals thebarPrintedcondition variable to allow thebarmethod to print "bar". - The
barmethod waits forfooDoneto be true. Once "bar" is printed, it resetsfooDoneto false and signals thefooPrintedcondition variable to allow the next iteration. - In the
mainfunction, we create two threads,threadFooandthreadBar, to execute thefooandbarmethods respectively. - The
pthread_joinfunction ensures the main thread waits for both threads to finish their execution.
Algorithm Walkthrough
Let’s emphasize synchronization aspects in the walkthrough to help understand how the program ensures proper ordering of "foo" and "bar" printing.
Initial Setup
- Create
foobar: An instance ofFooBarwithn = 5. - Initialize Synchronization Primitives:
mtx,fooPrinted, andbarPrinted. - Set Flag:
fooDoneis set tofalse.
Starting Threads
- Start
threadFoo: Initiatesfoobar.foo(), which contains the logic to print "foo". - Start
threadBar: Initiatesfoobar.bar(), which contains the logic to print "bar".
Walkthrough of Loop Iterations with Synchronization Focus:
Iteration 1
-
threadFoo:- Acquire Lock: Locks
mtxto enter the critical section. - Check Condition: Since
fooDoneisfalse, it proceeds without waiting. - Print "foo": Outputs "foo" to the console.
- Update Flag: Sets
fooDonetotrue. - Signal
threadBar: SignalsbarPrintedto wake upthreadBar(if it's waiting). - Release Lock: Unlocks
mtx.
- Acquire Lock: Locks
-
threadBar- Acquire Lock: Locks
mtxto enter the critical section. - Wait for "foo": Waits on
barPrinteduntilfooDoneistrue(ensures "foo" is printed before "bar"). - Print "bar": Outputs "bar" to the console (completing "foobar").
- Update Flag: Sets
fooDonetofalse. - Signal
threadFoo: SignalsfooPrintedto wake upthreadFoofor the next iteration. - Release Lock: Unlocks
mtx.
- Acquire Lock: Locks
Iterations 2 to 5
- Repeat the Steps: The same synchronization-focused steps as Iteration 1 are repeated. This ensures that "foo" is always printed before "bar" and "foobar" is printed 5 times in total.
Joining Threads
- Wait for
threadFoo:pthread_join(thread1, NULL)ensures the main thread waits untilthreadFoohas finished executing. - Wait for
threadBar:pthread_join(thread2, NULL)ensures the main thread waits untilthreadBarhas finished executing.
Final Result
- By the end of the program, "foobar" has been printed 5 times. The synchronization constructs (mutex and condition variables) have ensured that "foo" is always printed before "bar", maintaining the proper order despite the concurrent execution of threads. The program showcases a critical aspect of multithreading – ensuring coordinated execution and maintaining the integrity of shared resources (in this case, the order of "foo" and "bar" printing).

public class Solution {
private int n;
private boolean fooTurn = true; // Flag to determine which thread should run
public Solution(int n) {
this.n = n;
}
public synchronized void foo(Runnable printFoo) throws InterruptedException {
for (int i = 0; i < n; i++) {
// Wait while it's not foo's turn
while (!fooTurn) {
wait();
}
// printFoo.run() outputs "foo"
printFoo.run();
fooTurn = false; // Make it bar's turn
notify(); // Notify other thread to wake up
}
}
public synchronized void bar(Runnable printBar) throws InterruptedException {
for (int i = 0; i < n; i++) {
// Wait while it's not bar's turn
while (fooTurn) {
wait();
}
// printBar.run() outputs "bar"
printBar.run();
fooTurn = true; // Make it foo's turn
notify(); // Notify other thread to wake up
}
}
public static void main(String[] args) {
Solution foobar = new Solution(5);
// Threads to execute the foo and bar methods in parallel
Thread thread1 = new Thread(() -> {
try {
foobar.foo(() -> System.out.print("foo"));
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread thread2 = new Thread(() -> {
try {
foobar.bar(() -> System.out.print("bar"));
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// Start both threads
thread1.start();
thread2.start();
}
}
🤖 Don't fully get this? Learn it with Claude
Stuck on Problem 13 Synchronization of Dual Threads? 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 13 Synchronization of Dual Threads** (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 13 Synchronization of Dual Threads** 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 13 Synchronization of Dual Threads**. 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 13 Synchronization of Dual Threads**. 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.