哲学家就餐问题-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* ...
随机推荐
- 使用JavaMailSender 发送邮件
使用JavaMailSender 发送邮件 package com.juvenxu.mvnbook.account.email; import javax.mail.MessagingExceptio ...
- Super-Mario-Host(超级玛丽)靶机
仅供个人娱乐 靶机百度云下载 链接:https://pan.baidu.com/s/13l1FUgJjXArfoTOfcmPsbA 提取码:a8ox 一.主机发现 arp-scan -l 二.漏洞扫 ...
- 探索HashMap源码 一行一行解析 jdk1.7版本
今天我们来说一说,HashMap的源码到底是个什么? 面试大厂这方面一定会经常问到,很重要的.以jdk1.7 为标准 先带着大家过一遍 是由数组.链表组成 , 数组的优点是:每个元素有对应下标, ...
- JavaScript关于返回数据类型一个小小的笔记
Javascript关于返回数据类型的一个小笔记 javascript数据类型有两种. 一种是基本数据类型:String.Number.Boolean.Symbol.Underfine.Null 一种 ...
- 这才是做了五年Android开发该有的样子!
程序员工作五年后一般怎样了? 五年程序员生涯对身体上的摧残就不说了,来讲讲一般会有怎样的状态吧! 优秀的一般是这样:有着明确的职业目标与规划,热爱技术,五年的工作沉淀,技术能力得到了飞速提升,每天依然 ...
- 一周内被程序员疯转3.2W次,最终被大厂封杀的《字节跳动Android面试手册》!
一眨眼又到金三银四了,不知道各位有没有做好跳槽涨薪的准备了呢? 今天的话大家分享一份最新的<字节跳动Android面试手册>,内容包含Android基础+进阶,Java基础+进阶,数据结构 ...
- python 将Mnist数据集转为jpg,并按比例/标签拆分为多个子数据集
现有条件:Mnist数据集,下载地址:跳转 下载后的四个.gz文件解压后放到同一个文件夹下,如:/raw Step 1:将Mnist数据集转为jpg图片(代码来自这篇博客) 1 import os 2 ...
- java常见面试题总结2
JAVA必背面试题和项目面试通关要点 简单来讲,equals方法主要是用来判断从表面上看或者从内容上看,2个对象是不是相等. 一 数据库 1.常问数据库查询.修改(SQL查询包含筛选查询.聚合查询和链 ...
- 6.算法竞赛中的常用JAVA API :Math类(转载)
6.算法竞赛中的常用JAVA API :Math类 求最值 最小值 Math.min(int a, int b) Math.min(float a, float b) Math.min(double ...
- windows中抓取hash小结(下)
书接上回,windows中抓取hash小结(上) 指路链接 https://www.cnblogs.com/lcxblogs/p/13957899.html 继续 0x03 从ntds.dit中抓取 ...