Python Two Solutions
In both solutions, we have to analyze when a deadlock happens.  If a philosopher picks up 2 forks, then they will set them down after.  So a philosopher could o
In both solutions, we have to analyze when a deadlock happens.  If a philosopher picks up 2 forks, then they will set them down after.  So a philosopher could only really get stuck on 0 or 1 forks.  Its easy to see that this means a deadlock only occurs if 5 forks are picked up (1 for each philosopher).\n\n**Solution 1:**\nEnforce that at most 4 philosophers can approach the table with `sizelock`.  Then at most 4 forks are picked up, so there can\'t be a deadlock.\n\n**Solution 2:**\nEnforce that some philosophers pick up forks left then right, and others pick them up right then left.  Then a fork is preferred by two neighboring philosophers, guaranteeing that if one of them has 1 fork, the other has 0, and thus at most 4 forks are picked up.\n\n```\nfrom threading import Semaphore\n\nclass DiningPhilosophers:\n    def __init__(self):\n        self.sizelock = Semaphore(4)\n        self.locks = [Semaphore(1) for _ in range(5)]\n\n    def wantsToEat(self, index, *actions):\n        left, right = index, (index - 1) % 5\n        with self.sizelock:\n            with self.locks[left], self.locks[right]:\n                for action in actions:\n                    action()\n```\n\n```\nfrom threading import Semaphore\n\nclass DiningPhilosophers:\n    def __init__(self):\n        self.locks = [Semaphore(1) for _ in range(5)]\n\n    def wantsToEat(self, index, *actions):\n        left, right = index, (index - 1) % 5\n        \n        if index:\n            with self.locks[left], self.locks[right]:\n                for action in actions:\n                    action()\n        else:\n            with self.locks[right], self.locks[left]:\n                for action in actions:\n                    action()\n```
[]