Different python threading solutions (Lock, Barrier, Events, Semaphore, Condition) with explanation
\nStart with two locked locks. First thread unlocks the first lock that the second thread is waiting on. Second thread unlocks the second lock that the third th
\nStart with two locked locks. First thread unlocks the first lock that the second thread is waiting on. Second thread unlocks the second lock that the third thread is waiting on.\n\n# code\n```\nfrom threading import Lock\n\nclass Foo:\n    def __init__(self):\n        self.locks = (Lock(),Lock())\n        self.locks[0].acquire()\n        self.locks[1].acquire()\n        \n    def first(self, printFirst):\n        printFirst()\n        self.locks[0].release()\n        \n    def second(self, printSecond):\n        with self.locks[0]:\n            printSecond()\n            self.locks[1].release()\n            \n            \n    def third(self, printThird):\n        with self.locks[1]:\n            printThird()\n```\nRaise two barriers. Both wait for two threads to reach them.\n\nFirst thread can print before reaching the first barrier. Second thread can print before reaching the second barrier. Third thread can print after the second barrier.\n\n# code\n```\nfrom threading import Barrier\n\nclass Foo:\n    def __init__(self):\n        self.First_barrier = Barrier(2)\n        self.Second_barrier = Barrier(2)\n            \n    def first(self, printFirst):\n        printFirst()\n        self.First_barrier.wait()\n        \n    def second(self, printSecond):\n        self.First_barrier.wait()\n        printSecond()\n        self.Second_barrier.wait()\n            \n    def third(self, printThird):\n        self.Second_barrier.wait()\n        printThird()\n```\nSet events from first and second threads when they are done. Have the second thread wait for first one to set its event. Have the third thread wait on the second thread to raise its event.\n\n# code\n```\nfrom threading import Event\n\nclass Foo:\n    def __init__(self):\n        self.events = (Event(),Event())\n        \n    def first(self, printFirst):\n        printFirst()\n        self.events[0].set()\n        \n    def second(self, printSecond):\n        self.events[0].wait()\n        printSecond()\n        self.events[1].set()\n            \n    def third(self, printThird):\n        self.events[1].wait()\n        printThird()\n```\nStart with two closed gates represented by 0-value semaphores. Second and third thread are waiting behind these gates. When the first thread prints, it opens the gate for the second thread. When the second thread prints, it opens the gate for the third thread.\n\n# code\n```\nfrom threading import Semaphore\n\nclass Foo:\n    def __init__(self):\n        self.gates = (Semaphore(0),Semaphore(0))\n        \n    def first(self, printFirst):\n        printFirst()\n        self.gates[0].release()\n        \n    def second(self, printSecond):\n        with self.gates[0]:\n            printSecond()\n            self.gates[1].release()\n            \n    def third(self, printThird):\n        with self.gates[1]:\n            printThird()\n```\nHave all three threads attempt to acquire an RLock via Condition. The first thread can always acquire a lock, while the other two have to wait for the order to be set to the right value. First thread sets the order after printing which signals for the second thread to run. Second thread does the same for the third.\n\n# code\n```\nfrom threading import Condition\n\nclass Foo:\n    def __init__(self):\n        self.exec_condition = Condition()\n        self.order = 0\n        self.first_finish = lambda: self.order == 1\n        self.second_finish = lambda: self.order == 2\n\n    def first(self, printFirst):\n        with self.exec_condition:\n            printFirst()\n            self.order = 1\n            self.exec_condition.notify(2)\n\n    def second(self, printSecond):\n        with self.exec_condition:\n            self.exec_condition.wait_for(self.first_finish)\n            printSecond()\n            self.order = 2\n            self.exec_condition.notify()\n\n    def third(self, printThird):\n        with self.exec_condition:\n            self.exec_condition.wait_for(self.second_finish)\n            printThird()
['Python3']