有5个哲学家围着一张圆桌子,在每人的左右都有一根筷子,只有凑够两根筷子才可以吃饭,哲学家只有思考和吃饭两个动作,模拟这个过程,探究死锁的产生。
如果每个哲学家开始都是先拿起左边的筷子,等待着右边的人放下另外一根筷子,所有的哲学家都拿着一根筷子,所有的哲学家都在等筷子,这样就进入死锁的状态。
看一下代码实现:
哲学家类:
class Philosopher extends ReentrantLock implements Runnable{
private String name;
private volatile Chopstick leftChopstick;
private volatile Chopstick rightChopstick;
public Philosopher(String name, Chopstick leftChopstick, Chopstick rightChopstick) {
this.name = name;
this.leftChopstick = leftChopstick;
this.rightChopstick = rightChopstick;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Chopstick getLeftChopstick() {
return leftChopstick;
}
public void setLeftChopstick(Chopstick leftChopstick) {
this.leftChopstick = leftChopstick;
}
public Chopstick getRightChopstick() {
return rightChopstick;
}
public void setRightChopstick(Chopstick rightChopstick) {
this.rightChopstick = rightChopstick;
}
public void think() {
System.out.println("哲学家:"+name+" 正在思考");
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void eat() {
while (true) {
if(!leftChopstick.isHeld()) {
System.out.println("哲学家: "+name+"拿起了左边筷子:"+leftChopstick.getId());
leftChopstick.setHeld(true);
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
//System.out.println(leftChopstick.getId()+" "+leftChopstick.isHeld());
break;
} else {
think();
}
}
while (true) {
if(!rightChopstick.isHeld()) {
System.out.println("哲学家: "+name+"拿起了右边筷子:"+rightChopstick.getId());
rightChopstick.setHeld(true);
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
//System.out.println(rightChopstick.getId()+" "+rightChopstick.isHeld());
break;
} else {
think();
}
}
System.out.println("哲学家:" + name + "开始吃饭");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("哲学家: "+ name + "吃完");
leftChopstick.setHeld(false);
rightChopstick.setHeld(false);
}
@Override
public void run() {
eat();
}
}
筷子类:
class Chopstick {
private int id;
AtomicBoolean isHeld;
public Chopstick(int id, boolean isHeld) {
this.id = id;
this.isHeld = new AtomicBoolean(isHeld);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public boolean isHeld() {
return isHeld.get();
}
public void setHeld(boolean held) {
isHeld.getAndSet(held);
}
}
测试类:
public class PhilosopherEatTest {
public static void main(String[] args) {
Chopstick[] chopsticks = new Chopstick[5];
for (int i = 0; i < 5; i++) {
chopsticks[i] = new Chopstick(i,false);
}
Philosopher[] philosophers = new Philosopher[5];
for (int i = 0; i < 5; i++) {
philosophers[i] = new Philosopher(" "+i,chopsticks[i],chopsticks[(i+1)%5]);
}
for (int i = 0; i < 5; i++) {
new Thread(philosophers[i]).start();
}
}
}
我的实现思路就是每个哲学家线程默认先去尝试拿左边的筷子,拿筷子是需要时间的,这个时候所有的线程都拿起了左边的筷子,而右边的筷子都被右边的哲学家拿起,这样就出现了僵持状态,出现了死锁。
这个就是模拟过程。