哲学家就餐问题是在计算机科学中的一个经典问题,用来演示在并行计算中多线程同步(Synchronization)时产生的问题。
有五个哲学家,他们共用一张圆桌,分别坐在五张椅子上。在圆桌上有五个碗和五支筷子,平时一个哲学家进行思考,饥饿时便试图取用其左、右最靠近他的筷子,只有在他拿到两支筷子时才能进餐。进餐完毕,放下筷子。
code:
两个对象:Chopsticks 空。
public static class PhilosopherThread extends Thread {
private Chopsticks left;
private Chopsticks right;
private int index;
public PhilosopherThread(Chopsticks left, Chopsticks right, int index) {
this.left = left;
this.index = index;
this.right = right;
}
@Override
public void run() {
synchronized (left) {
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(index + "等待获取筷子left进行吃饭");
synchronized (right) {
System.out.println(index + "获取筷子RIGHT进行吃饭");
}
}
}
}
测试输出:
public static void main(String[] args) {
Chopsticks chopsticks1 = new Chopsticks();
Chopsticks chopsticks2 = new Chopsticks();
Chopsticks chopsticks3 = new Chopsticks();
Chopsticks chopsticks4 = new Chopsticks();
Chopsticks chopsticks5 = new Chopsticks();
PhilosopherThread philosopherThread1 = new PhilosopherThread(chopsticks1, chopsticks2, 1);
PhilosopherThread philosopherThread2 = new PhilosopherThread(chopsticks2, chopsticks3, 2);
PhilosopherThread philosopherThread3 = new PhilosopherThread(chopsticks3, chopsticks4, 3);
PhilosopherThread philosopherThread4 = new PhilosopherThread(chopsticks4, chopsticks5, 4);
PhilosopherThread philosopherThread5 = new PhilosopherThread(chopsticks5, chopsticks1, 5);
philosopherThread1.start();
philosopherThread2.start();
philosopherThread3.start();
philosopherThread4.start();
philosopherThread5.start();
}
输出 :
4等待获取筷子left进行吃饭
1等待获取筷子left进行吃饭
3等待获取筷子left进行吃饭
5等待获取筷子left进行吃饭
2等待获取筷子left进行吃饭
这是一种死锁。
换个方式:
一 同时对两把筷子加锁,正规写法是定义全局变量
public static class PhilosopherThread extends Thread {
private Chopsticks left;
private Chopsticks right;
private int index;
public PhilosopherThread(Chopsticks left, Chopsticks right, int index) {
this.left = left;
this.index = index;
this.right = right;
}
@Override
public void run() {
synchronized (left.toString()+right.toString()) {
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(index + "等待获取筷子RIGHT+left进行吃饭");
// synchronized (right) {
// System.out.println(index + "获取筷子RIGHT进行吃饭");
// }
}
}
}
输出:
2等待获取筷子RIGHT+left进行吃饭
1等待获取筷子RIGHT+left进行吃饭
4等待获取筷子RIGHT+left进行吃饭
3等待获取筷子RIGHT+left进行吃饭
5等待获取筷子RIGHT+left进行吃饭
二 奇偶互反
奇偶互反,奇数哲学家先取右边,偶数先取左边。
public static class PhilosopherThread extends Thread {
private Chopsticks left;
private Chopsticks right;
private int index;
public PhilosopherThread(Chopsticks left, Chopsticks right, int index) {
this.left = left;
this.index = index;
this.right = right;
}
@Override
public void run() {
if(index%2==0) {
synchronized (left) {
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (right) {
System.out.println(index + "吃完了");
}
}
}else{
synchronized (right) {
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (left) {
System.out.println(index + "吃完了");
}
}
}
}
}
输出 :
3吃完了
5吃完了
1吃完了
4吃完了
2吃完了