2 differnt Java Solution respectively using wait/notify and Semaphore
Explaination\n\nTwo different solutions actually share the same logic:\n\n1. Avoid deadlock by keeping the number of philosophers who holding forks under 4 (If 
## Explaination\n\nTwo different solutions actually share the same logic:\n\n1. Avoid deadlock by keeping the number of philosophers who holding forks under 4 (If 5 of them all have one fork, then they can never eat)\n2. Lock each fork before picking it, unlock each fork after putting it down.\n\nThe only difference is that reentrantlock is easier to implement. When using synchronized, if you synchronize on both two forks then it would be confusing and also tend to cause deadlock, so I use AtomicBoolean instead to define forks\' status.\n\nMy logic for both solutions take the left fork first and right fork secondly. Maybe we can use a random value to decide left first or right first, which might be more satisfying.\n\n## Wait/Notify\n\n```\nclass DiningPhilosophers {\n\n    public AtomicBoolean[] forks = new AtomicBoolean[5];\n    public AtomicInteger taken = new AtomicInteger(0);      // Avoid Deadlock\n    public DiningPhilosophers() {\n        forks[0] = new AtomicBoolean(true);\n        forks[1] = new AtomicBoolean(true);\n        forks[2] = new AtomicBoolean(true);\n        forks[3] = new AtomicBoolean(true);\n        forks[4] = new AtomicBoolean(true);\n    }\n\n    // call the run() method of any runnable to execute its code\n    public void wantsToEat(int philosopher,\n                           Runnable pickLeftFork,\n                           Runnable pickRightFork,\n                           Runnable eat,\n                           Runnable putLeftFork,\n                           Runnable putRightFork) throws InterruptedException {\n        int left = philosopher;\n        int right = (philosopher+4)%5;\n        synchronized(forks[left]){\n            while (!forks[left].get() || taken.get()==4){\n                forks[left].wait();\n            }\n            forks[left].compareAndSet(true, false);\n            taken.getAndIncrement();\n            pickLeftFork.run();\n        }\n        synchronized(forks[right]){\n            while (!forks[right].get()){\n                forks[right].wait();\n            }\n            forks[right].compareAndSet(true, false);\n            pickRightFork.run();  \n        }\n        eat.run();\n        synchronized(forks[left]){\n            forks[left].compareAndSet(false, true);\n            putLeftFork.run();\n            forks[left].notifyAll();\n        }\n        synchronized(forks[right]){\n            forks[right].compareAndSet(false, true);\n            putRightFork.run();\n            taken.getAndDecrement();\n            forks[right].notifyAll();\n        }\n    }\n}\n```\n\n## Semaphore + ReentrantLock\n\n```\nclass DiningPhilosophers {\n\n    public ReentrantLock[] forks = new ReentrantLock[5];\n    public Semaphore taken = new Semaphore(4);      // Avoid deadlock\n    public DiningPhilosophers() {\n        forks[0] = new ReentrantLock();\n        forks[1] = new ReentrantLock();\n        forks[2] = new ReentrantLock();\n        forks[3] = new ReentrantLock();\n        forks[4] = new ReentrantLock();\n    }\n\n    // call the run() method of any runnable to execute its code\n    public void wantsToEat(int philosopher,\n                           Runnable pickLeftFork,\n                           Runnable pickRightFork,\n                           Runnable eat,\n                           Runnable putLeftFork,\n                           Runnable putRightFork) throws InterruptedException {\n        \n        int left = philosopher;\n        int right = (philosopher+4)%5;\n        \n        taken.acquire();\n        \n        forks[left].lock();\n        pickLeftFork.run();\n        \n        forks[right].lock();\n        pickRightFork.run();\n\n        eat.run();\n        \n        putLeftFork.run();\n        forks[left].unlock();\n        \n        putRightFork.run();\n        forks[right].unlock();\n\n        taken.release();\n    }\n}\n```
['Java']