我十分不解,为什么在Philosopher类中的run()内增加pause()就能让死锁慢一点发生?请大神指教
这个例子中,产生死锁的原因在于,所有的哲学家都拿到了右筷子,却因为拿不到左筷子而陷入循环等待。但这和是否使用pause()有关系吗?可以注意到例子中使用的随机数赋予了种子,也就是说,每次运行得到的结果是一个固定且相同的值,即便是加了pause(),等待哪怕1000秒,当1000秒后,所有的哲学家仍然同时由等待状态转变成了可运行态,接着受到线程调度器分配时间片来驱动,这和等待时间的长短又有什么必然的关系呢???(ps: 我的理解是把种子去掉,不同的哲学家思考的时间不同,进入"拿筷子"阶段的时间不同,**降低同时请求共享资源的可能性**,这样倒是能缓解死锁发生的概率,书上的说法实在是无法理解)
请先避开不谈满足死锁的四个条件。直接讨论这个例子。
/**
* 哲学家问题 筷子
*/
public class Chopstick {
private boolean taken = false;
public synchronized void take(int id, String direction) throws InterruptedException{
while(taken) {
System.out.println("Philosopher " + id + " waiting " + direction + " chopstick");
this.wait();
}
// 现在由新的哲学家持有这根筷子
taken = true;
System.out.println("Philosopher " + id + " grabbed " + direction + " chopstick");
}
public synchronized void drop() {
taken = false;
this.notifyAll();
}
}
/**
* 哲学家问题 哲学家
*/
public class Philosopher implements Runnable{
private Chopstick left;
private Chopstick right;
private final int id;
private final int ponderFactor;
private Random rand = new Random(47);
private void pause() throws InterruptedException{
if(ponderFactor == 0) {
return;
}
TimeUnit.MILLISECONDS.sleep(rand.nextInt(ponderFactor * 250));
}
public Philosopher(Chopstick left, Chopstick right, int ident, int ponder) {
this.left = left;
this.right = right;
this.id = ident;
this.ponderFactor = ponder;
}
@Override
public void run() {
try {
while(!Thread.interrupted()) {
// 为什么加上的等待时间越长,产生死锁的可能性越小?
pause();
//System.out.println(this + " beginning eating " + LocalDateTime.now().getNano());
// 哲学家开始变饿
System.out.println(this + " " + "grabbing right");
right.take(id, "right");
System.out.println(this + " " + "grabbing left");
left.take(id, "left");
System.out.println(this + " " + "eating");
pause();
right.drop();
left.drop();
}
}catch (InterruptedException e) {
System.out.println(this + " " + "exiting via interrupt");
}
}
public String toString() {
return "Philosopher " + id;
}
}
/**
* 哲学家问题 演示死锁
*/
public class DeadlockingDiningPhilosopher {
public static void main(String[] args) throws InterruptedException, IOException {
int ponder = 5;
if(args.length > 0) {
ponder = Integer.parseInt(args[0]);
}
int size = 5;
if (args.length > 1) {
size = Integer.parseInt(args[1]);
}
ExecutorService exec = Executors.newCachedThreadPool();
Chopstick[] sticks = new Chopstick[size];
for(int i = 0; i < size; i++) {
sticks[i] = new Chopstick();
}
for (int i = 0; i < size; i++) {
exec.execute(new Philosopher(sticks[i], sticks[(i+1) % size], i, ponder));
}
if (args.length == 3 && args[2].equals("timeout")) {
TimeUnit.SECONDS.sleep(5);
} else {
System.out.println("Press 'Enter' to quit");
System.in.read();
}
exec.shutdownNow();
}
}