Python3 with 5 locks
1 lock for each fork. Philosopher tries to pick up both forks, if he can pick one up but not the other, change hands and try again. Point is to avoid deadlock w
1 lock for each fork. Philosopher tries to pick up both forks, if he can pick one up but not the other, change hands and try again. Point is to avoid deadlock where one guy got left fork and is waiting on the right, but the guy to the right is in the same situation. It\'s possible to end up in such a situation that everyone has one fork and is waiting for the other one. Giving up if you can\'t acquire it and changing them up avoids that.\n\n```\nfrom threading import Lock\n\nclass DiningPhilosophers:\n    def __init__(self, n: int = 5):\n        self.forks = [Lock() for _ in range(n)]\n        self.n = n\n\n    # call the functions directly to execute, for example, eat()\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        left_fork = self.forks[philosopher]\n        right_fork = self.forks[(philosopher + 1) % self.n]\n        \n        while True:\n            left_fork.acquire()\n            \n            if not right_fork.acquire(False):\n                left_fork.release()\n                left_fork, right_fork = right_fork, left_fork\n            else:\n                break\n            \n        pickLeftFork()\n        pickRightFork()\n                  \n        eat()\n        \n        putLeftFork()\n        putRightFork()\n        left_fork.release()\n        right_fork.release()\n```
['Python3']