哲学家就餐问题-Java语言实现死锁避免
哲学家就餐问题-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*/
哲学家就餐问题-Java语言实现死锁避免的更多相关文章
- 哲学家就餐问题 C语言实现
场景: 原版的故事里有五个哲学家(不过我们写的程序可以有N个哲学家),这些哲学家们只做两件事--思考和吃饭,他们思考的时候不需要任何共享资源,但是吃饭的时候就必须使用餐具,而餐桌上的餐具是有限的,原版 ...
- JAVA并发,经典死锁案例-哲学家就餐
转自:http://blog.csdn.net/tayanxunhua/article/details/38691005 死锁经典案例:哲学家就餐. 这个案例会导致死锁. 通过修改<Java编程 ...
- JAVA多线程学习--哲学家就餐问题
哲学家就餐问题是1965年由Dijkstra提出的一种线程同步的问题. 问题描述:一圆桌前坐着5位哲学家,两个人中间有一只筷子,桌子中央有面条.哲学家思考问题,当饿了的时候拿起左右两只筷子吃饭,必须拿 ...
- 进程同步——哲学家进餐问题Java实现
哲学家就餐问题是1965年由Dijkstra提出的一种线程同步的问题. 问题描述:一圆桌前坐着5位哲学家,两个人中间有一只筷子,桌子中央有面条.哲学家思考问题,当饿了的时候拿起左右两只筷子吃饭,必须拿 ...
- JAVA语言规范-线程和锁章节之同步、等待和通知
JAVA语言规范:线程和锁 1 同步 java编程语言提供了线程间通信的多种机制.这些方法中最基本的是同步化,此方法是使用监视器实现的.JAVA中每个对象与一个监视器相关联,一个线程可以加锁和解锁监视 ...
- 瘋耔java语言笔记
一◐ java概述 1.1 ...
- 基于JAVA语言的多线程技术
1.简介 多线程技术属于操作系统范围内的知识: 进程与线程 可以这么理解,一个应用程序就是一个进程,在一个进程中包含至少一个线程:进程就是线程的容器,真正工作.处理任务的是线程. 进程是操作系统分配资 ...
- linux下多线程互斥量实现生产者--消费者问题和哲学家就餐问题
生产者消费者问题,又有界缓冲区问题.两个进程共享一个一个公共的固定大小的缓冲区.其中一个是生产者,将信息放入缓冲区,另一个是消费者,从缓冲区中取信息. 问题的关键在于缓冲区已满,而此时生产者还想往其中 ...
- 已看1.熟练的使用Java语言进行面向对象程序设计,有良好的编程习惯,熟悉常用的Java API,包括集合框架、多线程(并发编程)、I/O(NIO)、Socket、JDBC、XML、反射等。[泛型]\
1.熟练的使用Java语言进行面向对象程序设计,有良好的编程习惯,熟悉常用的Java API,包括集合框架.多线程(并发编程).I/O(NIO).Socket.JDBC.XML.反射等.[泛型]\1* ...
随机推荐
- python3中匿名函数做参数,匿名函数做实参,eval关键字
一:说到匿名函数,大家都感到陌生又熟悉,今天我带大家了解一下py3中的匿名函数,以及匿名函数作为函数的参数的情况 主要通过以下实例来说明: 实例一: newarr =[33,44444,6222,88 ...
- 论文笔记:(CVPR2019)PointWeb: Enhancing Local Neighborhood Features for Point Cloud Processing
目录 摘要 一.引言 二.相关工作 3D数据表示 点云深度学习 三.我们的方法 3.1 自适应特征调整(AFA)模块 3.1.1 影响函数fimp 3.1.2 关系函数frel 3.1.3 逐元素影响 ...
- SuperEdge 高可用云边隧道有哪些特点?
作者 作者李腾飞,腾讯容器技术研发工程师,腾讯云TKE后台研发,SuperEdge核心开发成员. 背景 在边缘集群中,边缘端和云端为单向网络,云端无法主动连接边缘端,常见的解决方案是边缘端主动和云端( ...
- openssl查看证书命令
openssl x509部分命令打印出证书的内容:openssl x509 -in cert.pem -noout -text打印出证书的系列号openssl x509 -in cert.pem -n ...
- AspNetCore添加API限流
最近发现有客户在大量的请求我们的接口,出于性能考虑遂添加了请求频率限制. 由于我们接口请求的是.Net Core写的API网关,所以可以直接添加一个中间件,中间件中使用请求的地址当key,通过配置中心 ...
- 1~n数字中1出现的个数
1~n数字中1出现的个数 LeetCode 给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数. 感觉挺有意思 对于一个数,我们先局部分析一下,比如123456,我们考虑百位这个 ...
- Linux虚拟机配置SSH免密登录
本环境为CentOS 7(点击镜像下载iso文件),无图界面. 启动SSH服务 在/usr/sbin/有一个文件为sshd,然后输入绝对路径/usr/sbin/sshd即可开启ssh服务. 然后输入命 ...
- Linux 硬盘与硬件管理
硬件以文件系统(Filesystem)角度来看 文件系统:一个可被挂载的数据称为文件系统,每个操作系统可以使用的文件系统并不一样,windows98是FAT或者FAT16文件系统,而windows20 ...
- SpringCloud-技术专区-从源码层面让你认识Feign工作流程和运作机制
Feign工作流程源码解析 什么是feign:一款基于注解和动态代理的声明式restful http客户端. 原理 Feign发送请求实现原理 微服务启动类上标记@EnableFeignClients ...
- Sqli-Labs less23-24
less-23 23关和第1关很像,但是观察代码发现他对--+和#都进行了转义,不能再用这种方式注释 可以用新的注释符:;%00或者and和or语句进行闭合 语句:http://192.168.5.1 ...