Exponential backoff (python3)
A philosopher waits indefinitely until the left fork is available, picks it up, and waits a short time for the right fork. If he gets the right fork, he eats, O
A philosopher waits indefinitely until the left fork is available, picks it up, and waits a short time for the right fork. If he gets the right fork, he eats, Otherwise, he puts the left fork down. Then he repeats.\n\nEach time he waits for the right fork, he waits for a random duration that\'s about twice as long as last time. This waiting scheme has two benefits:\n\n* The amount of checks on the locks is logarithmic in the duration that philosophers spend eating; therefore, the algorithm scales well with longer eating durations. (It doesn\'t spin excessively.)\n* The probability of livelock and starvation approaches zero with each successive random wait.\n\n```\nimport math\nimport random\nimport threading\n\nclass ExponentialBackoff:\n    def __init__(self):\n        self.n_attempts = 0\n    \n    def wait(self):\n        duration = 0.001 * math.pow(2, (self.n_attempts + random.random()))\n        self.n_attempts += 1\n        return duration\n\nclass DiningPhilosophers:\n    def __init__(self):\n        self.forks = [threading.Lock() for _ in range(5)]\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        eb = ExponentialBackoff()\n        f_left = self.forks[philosopher % 5]\n        f_right = self.forks[(philosopher+1) % 5]\n        has_eaten = False\n        \n        while not has_eaten:\n            f_left.acquire()\n            if f_right.acquire(timeout=eb.wait()):\n                pickLeftFork()\n                pickRightFork()\n                eat()\n                putLeftFork()\n                putRightFork()\n                f_left.release()\n                f_right.release()\n                has_eaten = True\n            else:\n                f_left.release()\n````
['Python3']