多线程~哲学家就餐问题
测试1 前言
在网上看到了一个很好的例子解释了多线程里面的一些东西那就是哲学家就餐问题。
如图:以上有5个哲学家和5根筷子。一个哲学家必须同时有两个筷子,那么他才能够吃饭。但是如果想要同时抓住两根筷子,就会有一些问题产生
问题1:就拿哲学家1来说:他必须抓住他左右两边的筷子。那么此时哲学家2也抓住了他右边的筷子。那么哲学家1和哲学家2就会同时抓住1根筷子。就会出现锁竞争的问题。
问题2:如果5个哲学家都抓住了右手边的筷子,那么他们的左手都会等待其他筷子的释放,但是其他哲学家释放筷子必须先吃完饭(完成任务)才会释放,但是另外一根筷子又被其他哲学家抓住了,这样就形成了一个闭环,出现了死锁的问题。
那么闲来模拟这个死锁的问题:
新建个筷子类:
public class ChopStick {
}
package com.example.demo.thread;
/**
* @Author: liubujun
* @Date: 2022/6/14 20:15
*/
public class T01_DeadLock {
public static void main(String[] args) {
ChopStick cs0 = new ChopStick();
ChopStick cs1 = new ChopStick();
ChopStick cs2 = new ChopStick();
ChopStick cs3 = new ChopStick();
ChopStick cs4 = new ChopStick();
//每个哲学家需要获取两根筷子
Philosohper p0 = new Philosohper("p0", 0, cs0, cs1);
Philosohper p1 = new Philosohper("p1", 1, cs1, cs2);
Philosohper p2 = new Philosohper("p2", 2, cs2, cs3);
Philosohper p3 = new Philosohper("p3", 3, cs3, cs4);
Philosohper p4 = new Philosohper("p4", 4, cs4, cs0);
p0.start();
p1.start();
p2.start();
p3.start();
p4.start();
}
public static class Philosohper extends Thread{
//筷子左和筷子右
private ChopStick left, right;
//第几个哲学家
private int index;
public Philosohper(String name, int index,ChopStick left, ChopStick right) {
this.setName(name);
this.left = left;
this.right = right;
this.index = index;
}
@Override
public void run() {
//获取最左边的筷子
synchronized (left){
try {
Thread.sleep(1+index);
} catch (InterruptedException e) {
e.printStackTrace();
}
//然后获取最右边的筷子
synchronized (right){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(index+"号哲学家已经吃完");
}
}
}
}
}
那么结果可想而知会产生死锁问题。
那么如何解决这个问题呢?
解决问题首先需要知道这个问题产生的原因:是因为所有人都去拿左边的筷子,产生死锁的问题。那么我让其中一个人拿右边的筷子,其余的人拿左边的筷子。不就解决了吗。比如:哲学家1是左撇子那左边筷子,其他4个哲学家拿右边筷子,那么哲学家1右边的筷子就没人拿了。最后只能给哲学家1拿了。那哲学家1拿到两根筷子吃完饭释放筷子,其他的哲学家也可以吃饭了。
代码示例:
package com.example.demo.thread;
/**
* @Author: liubujun
* @Date: 2022/6/14 20:15
*/
public class T01_DeadLock {
public static void main(String[] args) {
ChopStick cs0 = new ChopStick();
ChopStick cs1 = new ChopStick();
ChopStick cs2 = new ChopStick();
ChopStick cs3 = new ChopStick();
ChopStick cs4 = new ChopStick();
//每个哲学家需要获取两根筷子
Philosohper p0 = new Philosohper("p0", 0, cs0, cs1);
Philosohper p1 = new Philosohper("p1", 1, cs1, cs2);
Philosohper p2 = new Philosohper("p2", 2, cs2, cs3);
Philosohper p3 = new Philosohper("p3", 3, cs3, cs4);
Philosohper p4 = new Philosohper("p4", 4, cs4, cs0);
p0.start();
p1.start();
p2.start();
p3.start();
p4.start();
}
public static class Philosohper extends Thread{
//筷子左和筷子右
private ChopStick left, right;
//第几个哲学家
private int index;
public Philosohper(String name, int index,ChopStick left, ChopStick right) {
this.setName(name);
this.left = left;
this.right = right;
this.index = index;
}
@Override
public void run() {
if (index == 0 ) {
//获取最左边的筷子
synchronized (left){
try {
Thread.sleep(1+index);
} catch (InterruptedException e) {
e.printStackTrace();
}
//然后获取最右边的筷子
synchronized (right){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(index+"号哲学家已经吃完");
}
}
}else {
//获取最左边的筷子
synchronized (right){
try {
Thread.sleep(1+index);
} catch (InterruptedException e) {
e.printStackTrace();
}
//然后获取最右边的筷子
synchronized (left){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(index+"号哲学家已经吃完");
}
}
}
}
}
}
运行结果:

这样是不是就解决问题了,看结果是解决了,但其实还有一个效率的问题。就是总共有5根筷子,这样的写法是只能有一个人先开始吃饭,但是5根筷子明明可以2个人开始吃饭,所以我们只需将哲学家所占数为为偶数设置为左撇子就可以了。效果是一样的。


浙公网安备 33010602011771号