Skip to content

Conversation

@aryaman0406
Copy link
Owner

The C++ code implements a thread synchronization mechanism to ensure the foo and bar methods print "foo" and "bar" alternately, $N$ times. This is the solution for LeetCode Problem 1115: Print FooBar Alternately.Here is the completed PR template:PR Title Format: 1115.Print FooBar Alternately.cpp💡 IntuitionThis is a classic concurrency problem that requires ensuring strict ordering between two separate threads: one running foo() and the other running bar(). The sequence must always be foo, bar, foo, bar, ... for a total of $N$ cycles. The simplest and most direct way to enforce this alternating execution order is by using two mutually exclusive locks (mutexes), one for each function, where the release of one lock signals the next function to proceed.✍️ ApproachThe solution uses two standard C++ mutexes, m1 and m2, to create a lock-step synchronization:Initialization:The constructor initializes n and, crucially, immediately locks m2.m1 is initially unlocked. This ensures that the foo thread, which tries to lock m1, is the first to acquire its lock and run.m2 is initially locked. This ensures that the bar thread, which tries to lock m2, will immediately block and wait until foo releases m2.foo() method:It iterates $N$ times.Acquire m1: m1.lock() ensures only one thread is printing "foo" at a time (though it's only the foo thread using it).Print: printFoo() executes.Release m2: m2.unlock() unblocks the bar thread, allowing it to proceed with its execution cycle.bar() method:It also iterates $N$ times.Acquire m2: m2.lock() forces the thread to wait until foo has released m2.Print: printBar() executes.Release m1: m1.unlock() unblocks the foo thread, allowing it to proceed with the next cycle.This pattern (lock $A$, run, unlock $B$ $\implies$ lock $B$, run, unlock $A$) guarantees the strict foo, bar alternation.Code Solution (C++)C++#include
#include

using namespace std;

class FooBar {
private:
int n;
// Mutex for the 'foo' thread
mutex m1;
// Mutex for the 'bar' thread
mutex m2;

public:
FooBar(int n) {
this->n = n;
// Initialize m1 as unlocked (default).
// Lock m2 initially, so 'bar' waits for 'foo' to release it.
m2.lock();
}

void foo(function<void()> printFoo) {
    
    for (int i = 0; i < n; i++) {
        // 1. Wait for 'bar' to signal (by unlocking m1)
        m1.lock();
    	// printFoo() outputs "foo". Do not change or remove this line.
    	printFoo();
        // 2. Signal 'bar' to proceed
        m2.unlock();
    }
}

void bar(function<void()> printBar) {
    
    for (int i = 0; i < n; i++) {
        // 1. Wait for 'foo' to signal (by unlocking m2)
        m2.lock();
    	// printBar() outputs "bar". Do not change or remove this line.
    	printBar();
        // 2. Signal 'foo' to proceed
        m1.unlock();
    }
}

};
🔗 Related IssuesBy submitting this PR, I confirm that:[x] This is my original work not totally AI generated[x] I have tested the solution thoroughly on leetcode[x] I have maintained proper PR description format[x] This is a meaningful contribution, not spam

Implement FooBar class to alternate printing 'foo' and 'bar'.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants