Skip to content

Print Foo Bar Alternately

leetcode

code (semaphore) wrong

class FooBar {
private:
    int n;
    std::binary_semaphore sem{0};

public:
    FooBar(int n) {
        this->n = n;
    }

    void foo(function<void()> printFoo) {

        for (int i = 0; i < n; i++) {
            // printFoo() outputs "foo". Do not change or remove this line.
            printFoo();
            sem.release();
        }
    }

    void bar(function<void()> printBar) {

        for (int i = 0; i < n; i++) {
            sem.acquire();
            // printBar() outputs "bar". Do not change or remove this line.
            printBar();
        }
    }
};

what is wrong?

  • it failed to wake the other thread after the first print. so the first thread will print "foo" and then block on sem.release() (because it is a binary semaphore), while the second thread will block on sem.acquire() and never get a chance to print "bar" (because count is 0).
  • we need to notify the other thread after each print, so that it can proceed to print the next part. We can use two semaphores to achieve this: one for "foo" and one for "bar".

code (semaphore) correct

class FooBar {
private:
    int n;
    std::binary_semaphore fo{0};
    std::binary_semaphore ba{1}; //very important to trigger the first print
public:
    FooBar(int n) {
        this->n = n;
    }

    void foo(function<void()> printFoo) {

        for (int i = 0; i < n; i++) {
            ba.acquire();
            // printFoo() outputs "foo". Do not change or remove this line.
            printFoo();
            fo.release();
        }
    }

    void bar(function<void()> printBar) {

        for (int i = 0; i < n; i++) {
            fo.acquire();
            // printBar() outputs "bar". Do not change or remove this line.
            printBar();
            ba.release();
        }
    }
};

questions

can we remove the for loop?

No, we cannot remove the for loop because we need to print "foo" and "bar" n times. The for loop ensures that the printing happens n times, and the semaphores ensure that the order of printing is maintained. If we remove the for loop, we would only print "foo" and "bar" once, which does not meet the requirements of the problem.