哲学家就餐问题-Java语言实现死锁避免

我死锁预防是至少破坏死锁产生的四个必要条件之一,带来的问题就是系统资源利用率低且不符合开发习惯,而死锁避免不是事先釆取某种限制措施破坏死锁的必要条件,只是注意避免死锁的最终发生。

哲学家就餐问题

5 个沉默寡言的哲学家围坐在圆桌前,每人面前一盘意面。叉子放在哲学家之间的桌面上。(5 个哲学家,5 根筷子)

所有的哲学家都只会在思考和进餐两种行为间交替。哲学家只有同时拿到左边和右边的筷子才能吃到面,而同一根筷子在同一时间只能被一个哲学家使用。每个哲学家吃完面后都需要把筷子放回桌面以供其他哲学家吃面。只要条件允许,哲学家可以拿起左边或者右边的筷子,但在没有同时拿到左右筷子时不能进食。

产生死锁的四个必要条件:

(1) 互斥条件:一个资源每次只能被一个进程使用。

(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

(3) 不可剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。

(4) 环路等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

只要系统发生了死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。

解除死锁:从死锁进程处剥夺资源;终止部分或全部进程

Java语言实现死锁避免Demo

加锁前检查需要的资源是否足够,只有哲学家两边的筷子都没人用时同时拿起

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock; class DiningPhilosophers {
//5根筷子的状态,0代表未使用,1代表已使用
public static int[] chopsticks = new int[5];
public static ReentrantLock lock = new ReentrantLock();
public static Condition condition = lock.newCondition(); public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new Thread(new Philosophers(i)).start();
}
} static class Philosophers implements Runnable {
public int No; public Philosophers(int no) {
No = no;
} private void eat() {
System.out.println("哲学家 " + No + " is eating");
try {
Thread.currentThread().sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
} private void think() {
System.out.println("哲学家 " + No + " is thinking");
try {
Thread.currentThread().sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
} private void takeChopsticks() {
lock.lock();
//如果右边的筷子和左边的筷子都没有被使用
if (chopsticks[No] == 0 && chopsticks[(No + 4) % 5] == 0) {
chopsticks[No] = 1;
chopsticks[(No + 4) % 5] = 1;
} else {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.unlock();
} private void putdownChopsticks() {
lock.lock();
chopsticks[No] = 0;
chopsticks[(No + 4) % 5] = 0;
condition.signalAll();
lock.unlock();
} @Override
public void run() {
while (true) {
this.think();
this.takeChopsticks();
this.eat();
this.putdownChopsticks();
}
}
}
}
/* 哲学家 0 is thinking
哲学家 4 is thinking
哲学家 1 is thinking
哲学家 3 is thinking
哲学家 2 is thinking
哲学家 0 is eating
哲学家 2 is eating
哲学家 2 is thinking
哲学家 0 is thinking
哲学家 1 is eating
哲学家 3 is eating
哲学家 4 is eating
哲学家 0 is eating
哲学家 3 is thinking
哲学家 2 is eating
哲学家 1 is thinking
……………………………… */

给锁添加时限:先拿起右边的筷子,再尝试拿左边的筷子,如果一段时间后依然没有拿到左边的筷子,则放下右边的筷子

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock; class DiningPhilosophers2 { public static ReentrantLock[] chopsticks = new ReentrantLock[5];
public static Condition[] conditions = new Condition[5]; public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
chopsticks[i] = new ReentrantLock();
conditions[i] = chopsticks[i].newCondition();
}
for (int i = 0; i < 5; i++) {
new Thread(new Philosophers(i)).start();
}
} static class Philosophers implements Runnable { public int No; public Philosophers(int no) {
No = no;
} private void eat() {
System.out.println("哲学家 " + No + " is eating");
try {
Thread.currentThread().sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
} private void think() {
System.out.println("哲学家 " + No + " is thinking");
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} private void takeChopsticks() {
//是否获取了两个筷子
boolean acquire = false;
while (true) {
if (chopsticks[No].tryLock()) {
while (true) {
if (!chopsticks[(No + 4) % 5].tryLock()) {
chopsticks[No].unlock();
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
acquire = true;
}
break;
}
if (acquire) {
chopsticks[(No + 4) % 5].unlock();
chopsticks[No].unlock();
break;
} }
}
} private void putdownChopsticks() {
chopsticks[(No + 4) % 5].lock();
chopsticks[No].lock();
conditions[No].signalAll();
conditions[(No + 4) % 5].signalAll();
chopsticks[(No + 4) % 5].unlock();
chopsticks[No].unlock();
} @Override
public void run() {
while (true) {
this.think();
this.takeChopsticks();
this.eat();
this.putdownChopsticks();
}
}
}
}
/* 哲学家 0 is thinking
哲学家 2 is thinking
哲学家 4 is thinking
哲学家 1 is thinking
哲学家 3 is thinking
哲学家 0 is eating
哲学家 2 is eating
哲学家 1 is eating
哲学家 3 is eating
哲学家 4 is eating
哲学家 0 is thinking
哲学家 1 is thinking
哲学家 2 is thinking
哲学家 0 is eating
哲学家 3 is thinking
哲学家 4 is thinking
哲学家 2 is eating
哲学家 1 is eating
哲学家 3 is eating
哲学家 0 is thinking
哲学家 2 is thinking
哲学家 1 is thinking
哲学家 4 is eating
哲学家 0 is eating
哲学家 3 is thinking
哲学家 1 is eating
哲学家 4 is thinking
哲学家 2 is eating
哲学家 3 is eating*/

最新文章

  1. Java中的比较
  2. CAS 之 集成RESTful API
  3. Java格式化输出
  4. mysql innodb存储引擎的聚集索引
  5. 【ASP.NET Web API教程】1 ASP.NET Web API入门
  6. JAVA入门[4]-IntelliJ IDEA配置Tomcat
  7. tee 命令详解
  8. 预置app/apk到系统 &amp;&amp; 预置so库进系统 &amp;&amp; 预置普通文件和文件夹进系统
  9. Excel坐标自动在AutoCad绘图_3
  10. L2-010 排座位 (并查集)
  11. C#作为客户端调用gsoap生成的C++服务端
  12. Maven学习 四 Eclipse与Maven结合的配置
  13. Part 6:静态文件--Django从入门到精通系列教程
  14. maven使用配置
  15. flask开发的CMS管理系统
  16. shell_exec
  17. Webpack中的sourcemap
  18. $Linux vi/vim编辑器常用命令与用法总结 (Markdown编辑版)
  19. 什么是事件代理?DOM2.0标准事件模型的三个阶段
  20. bzoj 3895: 取石子

热门文章

  1. ts 学习笔记-基础篇
  2. CAS 原理 应用
  3. UI_UE在线就业-笔记
  4. JavaGUI输入框事件监听的使用
  5. linux 高并发socket通信模型
  6. CleanArchitecture Application代码生成插件-让程序员告别CURD Ctrl+C Ctrl+V
  7. 那些shellcode免杀总结
  8. ☕【Java技术指南】「Guava Collections」实战使用相关Guava不一般的集合框架
  9. 联合迭代器与生成器,enumerate() 内置函数真香!
  10. idea中导包出现import org.apach.*,提交代码老出现冲突,不想使用.*的设置