1.处理方式。同时只能有一个人去拿筷子,而且必须同时拿起两根筷子。所以用了一个mutex信号量。
解释:
假设当前用户A获得了mutex信号量之后,A先去拿left筷子,A再去right筷子。假设A此刻left拿不起来,说明有人(假设是B)在拿起了这根left筷子,同时B肯定也拿起了B需要的另一根筷子(因为如果B没有拿起B需要的另一个筷子,B就不会释放mutex,从而A就不能获得mutex,更别说A能拿起这根left筷子了),
所以B是能够吃上饭的。吃完饭便能放下这个left筷子,让A拿这根left子。同理A也能拿到right筷子。
import java.util.Arrays; import java.util.Date; import java.util.concurrent.Semaphore; enum PhiState{ THINKING,EATING,HUNGRY } /** * 死锁问题被认为是线程/进程间切换消耗系统性能的一种极端情况。 * 在死锁时,线程/进程间相互等待资源,而又不释放自身的资源,导致无穷无尽的等待,其结果是任务永远无法执行完成。 * 哲学家问题便是线程资源竞争导致的死锁现象,在程序运行一段时间后,程序所处的状态是n位哲学家(n个线程)都各自获取了一只筷子的状态, * 此时所有哲学家都想获取第二只筷子去吃饭,但是共享资源n只筷子已经都被n位哲学家握在手里了, * 彼此想要的筷子都在其他哲学家手中,又没有机制能让任何哲学家放弃握在手中的筷子,从而照成了所有哲学家(所有线程)都在等待其他人手中资源的死锁问题。 * @author win7 * */ //只要不存在每个人都拿起一根筷子,再想拿另一个筷子的时候都没有,就不会产生死锁。 public class PhiEat { Semaphore[] s; // 每个资源对应一个信号量(筷子) Semaphore mutex; // 互斥信号量,保证每次拿筷子的只有一个人 volatile PhiState[] state; // 记录哲学家当前的状态() int n; public PhiEat(int n) { // TODO Auto-generated constructor stub s = new Semaphore[n]; for (int i = 0; i < s.length; i++) { s[i] = new Semaphore(1); } mutex = new Semaphore(1); state = new PhiState[n]; for (int i = 0; i < state.length; i++) { state[i]=PhiState.THINKING; } this.n = n; } // 拿起两根筷子 public void take_two(int i){ int left = (i+n-1)%n; int right = (i+1)%n; try { mutex.acquire(); //因为有一个mutex信号量,保证了每次拿筷子的只有一个人。其他人要么此刻拿起来了两根筷子,要么一根筷子也没拿。 s[left].acquire(); s[right].acquire(); mutex.release(); } catch (Exception e) { e.printStackTrace(); } } // 放下两根筷子 public void put_two(int i){ int left = (i+n-1)%n; int right = (i+1)%n; s[left].release(); s[right].release(); } public void eat(int i){ try { state[i] = PhiState.EATING; System.out.println("哲学家"+i+"开始吃东西eating"); // Thread.sleep(1000); state[i] = PhiState.THINKING; System.out.println("哲学家"+i+"eating结束, 开始thinking"); } catch (Exception e) { e.printStackTrace(); } } public void think(int i){ try { System.out.println("哲学家"+i+"正在思考thinking"); // Thread.sleep(1000); state[i] = PhiState.HUNGRY; System.out.println("哲学家"+i+"thinking结束,变得hungry"); } catch (Exception e) { e.printStackTrace(); } } public void philosopher(int i){ while(true){ think(i); take_two(i); eat(i); put_two(i); } } public static void main(String[] args) throws InterruptedException { final int N=10; PhiEat pe = new PhiEat(N); for (int i = 0; i < N; i++) { final int num = i; new Thread(()->pe.philosopher(num)).start(); } // 本来是想在主线程用循环去查询当前线程的状态,但是在子线程中①号语句执行完毕,②号语句执行之前,可能切换到了主线程输出了当前线程的状态,导致②号语句没来得及打印 // state[i] = PhiState.HUNGRY; //① // System.out.println("哲学家"+i+"thinking结束,变得hungry"); //② // while(true){ // Thread.sleep(100); // System.out.println(Arrays.toString(pe.state)); // } } }