Python 3: Standard and simple solutions
Standard\nUsing 5 Locks to represent the 5 available forks, we have odd-numbered philosophers pick up the forks to their left and right and even-numbered philos
## Standard\nUsing 5 `Lock`s to represent the 5 available forks, we have odd-numbered philosophers pick up the forks to their left and right and even-numbered philosophers pick up the forks to their right and left before eating.\n\n```\nimport threading\n\n\nclass DiningPhilosophers:\n    def __init__(self):\n        self.forks = [threading.Lock() for _ in range(5)]\n\n    def wantsToEat(self,\n                   philosopher: int,\n                   pickLeftFork: \'Callable[[], None]\',\n                   pickRightFork: \'Callable[[], None]\',\n                   eat: \'Callable[[], None]\',\n                   putLeftFork: \'Callable[[], None]\',\n                   putRightFork: \'Callable[[], None]\') -> None:\n\n        first = philosopher\n        second = philosopher + 1 if philosopher < 4 else 0\n\n        if philosopher & 1:\n            first, second = second, first\n\n        with self.forks[first], self.forks[second]:\n            pickLeftFork()\n            pickRightFork()\n            eat()\n            putRightFork()\n            putLeftFork()\n```\n\n## Simple\nWe use a single `Condition` to allow only one philosopher to pick up forks and eat at a time. A thread must acquire the `Lock` associated with the `Condition` before it is allowed to eat. When the first thread is done and releases the `Lock`, if there are any other threads waiting for the `Condition`, one of them is notified and allowed to proceed.\n\nA `Semaphore` may be used instead of a `Condition`. This doesn\'t use a `Lock` but the observed behavior is identical with the default `value` of `1`.\n\nBecause of the GIL, this simple solution isn\'t really any slower in Python.\n```\nimport threading\n\n\nclass DiningPhilosophers:\n    def __init__(self):\n        self.eating = threading.Condition()  # or threading.Semaphore()\n\n    def wantsToEat(self, _, *funcs):\n        with self.eating:\n            for func in funcs:\n                func()\n```
[]