哲学家进餐问题的解决方案主要有以下几种:
(1) 利用AND 型信号量机制.该方案的思路是,仅当哲学家左右两支筷子都空闲时,才允许他拿起筷子进餐,即哲学家所需要的临界资源──筷子,要么两支全部分配给他,要么一支都不分配,这样就保证了总有哲学家能同时拿到两支筷子而进餐,当他进餐完毕释放筷子后,其他哲学家也可以顺利地运行下去,避免了死锁的产生.
(2) 对哲学家按序号进行区分.该方案的思路是,让第0、2、4 号哲学家先去申请他们左手边的筷子(即第0、2、4 号筷子),然后再去申请右手边的筷子,让第1、3 号哲学家先申请他们右手边的筷子(即第2、4 号筷子),然后再申请左手边的筷子.这样总会有一名哲学家能够同时拿到两支筷子而进餐,当他进餐完毕,释放其左右手的筷子后,其他哲学家又能继续下去,从而确保每位哲学家都可以顺利地进餐.
(3) 最多允许4 名哲学家提出申请.该方案的思路是,至多允许4 名哲学家提出进餐申请,以保证至少有1 名哲学家能够拿到两支筷子而进餐,他最终总会释放出所使用的两支筷子,从而使其余哲学家可以进餐.
(4)回退思想的引入回退机制的理论依据是处理死锁基本方法中的预防死锁策略.预防死锁是指通过设置某些限制条件,去破坏产生死锁的4 个必要条件中的一个或几个来防止死锁的发生.其中“摒弃不剥夺条件”规定,当一个进程提出新的资源请求而不能立即得到满足时,必须释放其已经保持了的所有资源,即已经占有的资源可以被剥夺.根据上面的理论,本文解决哲学家进餐问题的基本思路是,让每名哲学家先去申请他左手边的筷子,然后再申请他右手边的筷子,如果右手边的筷子不空闲,则比较当前哲学家i 和他右手边的哲学家(i +1)%5,看谁取得各自左手边筷子的时间更晚,令其回退(即释放左手筷子,再重新申请左手筷子),直到此哲学家右手边的筷子空闲为止.通过设置回退机制,可以确保每位哲学家都能顺利进餐.
我的方案:最后一个人先拿左筷,其他人都先拿右筷。(破坏死锁链)
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package tr52_java;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Philosopher extends Thread {
private static int MAX_PHILO = 4;
private int num;
private ChopStick right, left;
private boolean finished = false;
private Random rand = new Random();
private boolean flag = true;
public Philosopher(int i, ChopStick r, ChopStick l) {
num = i;
right = r;
left = l;
start();
}
public void pause() {
try {
sleep(rand.nextInt(1000));
} catch (Exception e) {
e.printStackTrace();
}
}
//会死锁!死锁点在synchronized(left)
// @Override
// public void run() {
// while (!finished) {
// flag = true;
// synchronized (right) {
// while (!right.isFree()) {
// try {
// right.wait();
// } catch (InterruptedException ex) {
// Logger.getLogger(Philosopher.class.getName()).log(Level.SEVERE, null, ex);
// }
// }
// pause();
// synchronized (left) {
// while (!left.isFree()) {
// flag = false;
// right.notify();
// System.out.println(num + "is thinking");
// break;
// }
// if (flag) {
// right.take();
// System.out.println(num + ": right taking");
// pause();
//
// left.take();
// System.out.println(num + ": left taking");
// pause();
//
// System.out.println(num + ": eating");
//
// right.release();
// right.notifyAll();
// System.out.println(num + ": right releasing");
// pause();
//
// left.release();
// left.notifyAll();
// System.out.println(num + ": left releasing");
// pause();
// }
// }
// }
// }
// }
@Override
public void run() {
while (!finished) {
System.out.println(num + "is thinking");
synchronized (right) {
while (!right.isFree()) {
try {
right.wait();
} catch (InterruptedException ex) {
Logger.getLogger(Philosopher.class.getName()).log(Level.SEVERE, null, ex);
}
}
right.take();
System.out.println(num + ": right taking");
pause();
}
synchronized (left) {
while (!left.isFree()) {
try {
left.wait();
} catch (InterruptedException ex) {
Logger.getLogger(Philosopher.class.getName()).log(Level.SEVERE, null, ex);
}
}
left.take();
System.out.println(num + ": left taking");
pause();
}
System.out.println(num + ": eating");
synchronized (right) {
right.release();
right.notifyAll();
System.out.println(num + ": right releasing");
pause();
}
synchronized (left) {
left.release();
left.notifyAll();
System.out.println(num + ": left releasing");
pause();
}
}
}
// @Override
// public void run() {
// while (!finished) {
// right.take();
// pause();
// left.take();
// pause();
// left.release();
// pause();
// right.release();
// pause();
// }
// }
public static void main(String[] args) {
ChopStick[] chopStick = new ChopStick[MAX_PHILO];
for (int i = 0; i < MAX_PHILO; i++) {
chopStick[i] = new ChopStick(i);
}
Philosopher[] phil = new Philosopher[MAX_PHILO];
for (int i = 0; i < MAX_PHILO; i++) {
if (i < MAX_PHILO - 1) {
phil[i] = new Philosopher(i, chopStick[i], chopStick[i > 0 ? i - 1 : MAX_PHILO - 1]);
} else {
phil[i] = new Philosopher(i, chopStick[i - 1], chopStick[i]);
}
}
}
}
class ChopStick {
private int num;
private boolean free = true;
public ChopStick(int i) {
num = i;
}
//方案1:
public void take() {
free = false;
}
public boolean isFree() {
return free;
}
public void release() {
free = true;
}
// public synchronized void take() {
// free = false;
// }
//
// public boolean isFree() {
// return free;
// }
//
// public synchronized void release() {
// free = true;
// }
}
(1) 利用AND 型信号量机制.该方案的思路是,仅当哲学家左右两支筷子都空闲时,才允许他拿起筷子进餐,即哲学家所需要的临界资源──筷子,要么两支全部分配给他,要么一支都不分配,这样就保证了总有哲学家能同时拿到两支筷子而进餐,当他进餐完毕释放筷子后,其他哲学家也可以顺利地运行下去,避免了死锁的产生.
(2) 对哲学家按序号进行区分.该方案的思路是,让第0、2、4 号哲学家先去申请他们左手边的筷子(即第0、2、4 号筷子),然后再去申请右手边的筷子,让第1、3 号哲学家先申请他们右手边的筷子(即第2、4 号筷子),然后再申请左手边的筷子.这样总会有一名哲学家能够同时拿到两支筷子而进餐,当他进餐完毕,释放其左右手的筷子后,其他哲学家又能继续下去,从而确保每位哲学家都可以顺利地进餐.
(3) 最多允许4 名哲学家提出申请.该方案的思路是,至多允许4 名哲学家提出进餐申请,以保证至少有1 名哲学家能够拿到两支筷子而进餐,他最终总会释放出所使用的两支筷子,从而使其余哲学家可以进餐.
(4)回退思想的引入回退机制的理论依据是处理死锁基本方法中的预防死锁策略.预防死锁是指通过设置某些限制条件,去破坏产生死锁的4 个必要条件中的一个或几个来防止死锁的发生.其中“摒弃不剥夺条件”规定,当一个进程提出新的资源请求而不能立即得到满足时,必须释放其已经保持了的所有资源,即已经占有的资源可以被剥夺.根据上面的理论,本文解决哲学家进餐问题的基本思路是,让每名哲学家先去申请他左手边的筷子,然后再申请他右手边的筷子,如果右手边的筷子不空闲,则比较当前哲学家i 和他右手边的哲学家(i +1)%5,看谁取得各自左手边筷子的时间更晚,令其回退(即释放左手筷子,再重新申请左手筷子),直到此哲学家右手边的筷子空闲为止.通过设置回退机制,可以确保每位哲学家都能顺利进餐.
同步和死锁的关系要搞清楚:
同步是为了保护多线程对共享数据的访问,消除数据腐蚀。同步的过程中可能会产生死锁!
也就是说,会产生死锁的程序中,共享数据得到了保护,只是程序会死锁。
我的方案:最后一个人先拿左筷,其他人都先拿右筷。(破坏死锁链)
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package tr52_java;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Philosopher extends Thread {
private static int MAX_PHILO = 4;
private int num;
private ChopStick right, left;
private boolean finished = false;
private Random rand = new Random();
private boolean flag = true;
public Philosopher(int i, ChopStick r, ChopStick l) {
num = i;
right = r;
left = l;
start();
}
public void pause() {
try {
sleep(rand.nextInt(1000));
} catch (Exception e) {
e.printStackTrace();
}
}
//会死锁!死锁点在synchronized(left)
// @Override
// public void run() {
// while (!finished) {
// flag = true;
// synchronized (right) {
// while (!right.isFree()) {
// try {
// right.wait();
// } catch (InterruptedException ex) {
// Logger.getLogger(Philosopher.class.getName()).log(Level.SEVERE, null, ex);
// }
// }
// pause();
// synchronized (left) {
// while (!left.isFree()) {
// flag = false;
// right.notify();
// System.out.println(num + "is thinking");
// break;
// }
// if (flag) {
// right.take();
// System.out.println(num + ": right taking");
// pause();
//
// left.take();
// System.out.println(num + ": left taking");
// pause();
//
// System.out.println(num + ": eating");
//
// right.release();
// right.notifyAll();
// System.out.println(num + ": right releasing");
// pause();
//
// left.release();
// left.notifyAll();
// System.out.println(num + ": left releasing");
// pause();
// }
// }
// }
// }
// }
@Override
public void run() {
while (!finished) {
System.out.println(num + "is thinking");
synchronized (right) {
while (!right.isFree()) {
try {
right.wait();
} catch (InterruptedException ex) {
Logger.getLogger(Philosopher.class.getName()).log(Level.SEVERE, null, ex);
}
}
right.take();
System.out.println(num + ": right taking");
pause();
}
synchronized (left) {
while (!left.isFree()) {
try {
left.wait();
} catch (InterruptedException ex) {
Logger.getLogger(Philosopher.class.getName()).log(Level.SEVERE, null, ex);
}
}
left.take();
System.out.println(num + ": left taking");
pause();
}
System.out.println(num + ": eating");
synchronized (right) {
right.release();
right.notifyAll();
System.out.println(num + ": right releasing");
pause();
}
synchronized (left) {
left.release();
left.notifyAll();
System.out.println(num + ": left releasing");
pause();
}
}
}
// @Override
// public void run() {
// while (!finished) {
// right.take();
// pause();
// left.take();
// pause();
// left.release();
// pause();
// right.release();
// pause();
// }
// }
public static void main(String[] args) {
ChopStick[] chopStick = new ChopStick[MAX_PHILO];
for (int i = 0; i < MAX_PHILO; i++) {
chopStick[i] = new ChopStick(i);
}
Philosopher[] phil = new Philosopher[MAX_PHILO];
for (int i = 0; i < MAX_PHILO; i++) {
if (i < MAX_PHILO - 1) {
phil[i] = new Philosopher(i, chopStick[i], chopStick[i > 0 ? i - 1 : MAX_PHILO - 1]);
} else {
phil[i] = new Philosopher(i, chopStick[i - 1], chopStick[i]);
}
}
}
}
class ChopStick {
private int num;
private boolean free = true;
public ChopStick(int i) {
num = i;
}
//方案1:
public void take() {
free = false;
}
public boolean isFree() {
return free;
}
public void release() {
free = true;
}
// public synchronized void take() {
// free = false;
// }
//
// public boolean isFree() {
// return free;
// }
//
// public synchronized void release() {
// free = true;
// }
}
没有评论:
发表评论