C++ | 2 Codes | Trick | conditional variable |
Intuition\n Describe your first thoughts on how to solve this problem. \nThe intuition is to use a condition_variable and a boolean flag (isFooTurn) to determin
# Intuition\n<!-- Describe your first thoughts on how to solve this problem. -->\nThe intuition is to use a **condition_variable** and a **boolean** **flag** (**isFooTurn**) to determine which thread\'s turn it is. The threads acquire a unique lock on a mutex before performing their operations. If it\'s not their turn, they wait on the condition_variable until it\'s signaled by the other thread. Once it\'s their turn, they perform their operation (printing) and change the flag to indicate the other thread\'s turn. Finally, they notify one waiting thread to proceed.\n\n \n\n# Code 1\n```  \n \n\nclass FooBar {\nprivate:\n    int n;\n    std::condition_variable turn;\n    std::mutex m;\n    std::atomic<bool> isFooTurn;\n\npublic:\n    FooBar(int n) {\n        this->n = n;\n        isFooTurn.store(true); // Start with foo\'s turn\n    }\n\n    void foo(std::function<void()> printFoo) {\n        std::unique_lock<std::mutex> lock(m);\n        for (int i = 0; i < n; i++) {\n            // Wait until it\'s foo\'s turn\n            turn.wait(lock, [this]() { return isFooTurn.load(); });\n            // Print "foo"\n            printFoo();\n            // Change the turn to bar\n            isFooTurn.store(false);\n            // Notify one waiting thread (bar) to proceed\n            turn.notify_one();\n        }\n    }\n\n    void bar(std::function<void()> printBar) {\n        std::unique_lock<std::mutex> lock(m);\n        for (int i = 0; i < n; i++) {\n            // Wait until it\'s bar\'s turn\n            turn.wait(lock, [this]() { return !isFooTurn.load(); });\n            // Print "bar"\n            printBar();\n            // Change the turn to foo\n            isFooTurn.store(true);\n            // Notify one waiting thread (foo) to proceed\n            turn.notify_one();\n        }\n    }\n};\n\n```\n\n# Code 2\n```\n \n\nclass FooBar {\nprivate:\n    int n;\n    std::mutex m1, m2; // Two mutexes to synchronize foo and bar\n\npublic:\n    FooBar(int n) {\n        this->n = n;\n        m2.lock(); // Lock m2 initially to ensure foo starts first\n    }\n\n    void foo(function<void()> printFoo) {\n        for (int i = 0; i < n; i++) {\n            m1.lock(); // Acquire lock on m1\n            // printFoo() outputs "foo". Do not change or remove this line.\n            printFoo();\n            m2.unlock(); // Release lock on m2 to allow bar to proceed\n        }\n    }\n\n    void bar(function<void()> printBar) {\n        for (int i = 0; i < n; i++) {\n            m2.lock(); // Acquire lock on m2\n            // printBar() outputs "bar". Do not change or remove this line.\n            printBar();\n            m1.unlock(); // Release lock on m1 to allow foo to proceed\n        }\n    }\n};\n\n```\n\n
['C++']