Java - Synchronized/Lock/Semaphore/Condition Variable
Synchronized Method:\n\nclass Foo {\n    private boolean oneDone;\n    private boolean twoDone;\n    \n    public Foo() {\n        oneDone = false;\n        two
Synchronized Method:\n```\nclass Foo {\n    private boolean oneDone;\n    private boolean twoDone;\n    \n    public Foo() {\n        oneDone = false;\n        twoDone = false;\n    }\n\n    public synchronized void first(Runnable printFirst) throws InterruptedException {\n        printFirst.run();\n        oneDone = true;\n        notifyAll();\n    }\n\n    public synchronized void second(Runnable printSecond) throws InterruptedException {\n        while (!oneDone) {\n            wait();\n        }\n        printSecond.run();\n        twoDone = true;\n        notifyAll();\n    }\n\n    public synchronized void third(Runnable printThird) throws InterruptedException {\n        while (!twoDone) {\n            wait();\n        }\n        printThird.run();\n    }\n}\n```\n\nSynchronized on Object:\n```\nclass Foo {\n    private Object lock;\n    private boolean oneDone;\n    private boolean twoDone;\n    \n    public Foo() {\n        lock = new Object();\n        oneDone = false;\n        twoDone = false;\n    }\n\n    public void first(Runnable printFirst) throws InterruptedException {\n        synchronized (lock) {\n            printFirst.run();\n            oneDone = true;\n            lock.notifyAll();\n        }\n    }\n\n    public void second(Runnable printSecond) throws InterruptedException {\n        synchronized (lock) {\n            while (!oneDone) {\n                lock.wait();\n            }\n            printSecond.run();\n            twoDone = true;\n            lock.notifyAll();\n        }\n    }\n\n    public void third(Runnable printThird) throws InterruptedException {\n        synchronized (lock) {\n            while (!twoDone) {\n                lock.wait();\n            }\n            printThird.run();\n        }\n    }\n}\n```\nSynchronized on Two Objects (not needed for this question, just put it here in case someone wants to use one object to protect one variable):\n```\nclass Foo {\n    private Object lock1;\n    private Object lock2;\n    private boolean oneDone;\n    private boolean twoDone;\n    \n    public Foo() {\n        lock1 = new Object();\n        lock2 = new Object();\n        oneDone = false;\n        twoDone = false;\n    }\n\n    public void first(Runnable printFirst) throws InterruptedException {\n        synchronized (lock1) {\n            printFirst.run();\n            oneDone = true;\n            lock1.notifyAll();\n        }\n    }\n\n    public void second(Runnable printSecond) throws InterruptedException {\n        synchronized (lock1) {\n            synchronized (lock2) {\n                while (!oneDone) {\n                    lock1.wait();\n                }\n                printSecond.run();\n                twoDone = true;\n                lock2.notifyAll();\n            }\n        }\n    }\n\n    public void third(Runnable printThird) throws InterruptedException {\n        synchronized (lock2) {\n            while (!twoDone) {\n                lock2.wait();\n            }\n            printThird.run();\n        }\n    }\n}\n```\nSemaphore:\n```\nclass Foo {\n    private Semaphore s2;\n    private Semaphore s3;\n    \n    public Foo() {\n        s2 = new Semaphore(0);\n        s3 = new Semaphore(0);\n    }\n\n    public void first(Runnable printFirst) throws InterruptedException {\n        printFirst.run();\n        s2.release();\n    }\n\n    public void second(Runnable printSecond) throws InterruptedException {\n        s2.acquire();\n        printSecond.run();\n        s3.release();\n    }\n\n    public void third(Runnable printThird) throws InterruptedException {\n        s3.acquire();\n        printThird.run();\n    }\n}\n```\nCondition Variable:\n```\nclass Foo {\n    private Lock lock;\n    private boolean oneDone;\n    private boolean twoDone;\n    private Condition one;\n    private Condition two;\n    \n    public Foo() {\n        lock = new ReentrantLock();\n        one = lock.newCondition();\n        two = lock.newCondition();\n        oneDone = false;\n        twoDone = false;\n    }\n\n    public void first(Runnable printFirst) throws InterruptedException {\n        lock.lock();\n        try {\n            printFirst.run();\n            oneDone = true;\n            one.signal();\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public void second(Runnable printSecond) throws InterruptedException {\n        lock.lock();\n        try {\n            while (!oneDone) {\n                one.await();\n            }\n            printSecond.run();\n            twoDone = true;\n            two.signal();\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public void third(Runnable printThird) throws InterruptedException {\n        lock.lock();\n        try {\n            while (!twoDone) {\n                two.await();\n            }\n            printThird.run();\n        } finally {\n            lock.unlock();\n        }\n    }\n}\n```
['Java']