并发死锁与进程
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
黑龙江大学
实验报告
黑龙江大学教务处
一、实验目的
1、加深对进程感念的理解,明确进程和程序的区别。
2、进一步认识并发执行的实质。
3、分析进程争用资源的现象,学习解决进程互斥的方法。
二、实验环境
1、编程语言:Java语言
2、开发环境:JDK 1.8.0、Intellij IDEA 2016.2、macOS
三、实验内容
(一)哲学家就餐
1、问题描述
哲学家就餐问题可以这样表述,假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。吃东西的时候,他们就停止思考,思考的时候也停止吃东西。餐桌中间有一大碗意大利面,每两个哲学家之间有一只餐叉。
2、问题分析
哲学家从来不交谈,这就很危险,可能产生死锁,每个哲学家都拿着左手的餐叉,永远都在等右边的餐叉(或者相反)。即使没有死锁,也有可能发生资源耗尽。例如,假设规定当哲学家等待另一只餐叉超过五分钟后就放下自己手里的那一只餐叉,并且再等五分钟后进行下一次尝试。这个策略消除了死锁(系统总会进入到下一个状态),但仍然有可能发生“活锁”。
3、死锁现象程序举例:
(1)死锁程序清单:
程序清单1-1 Chopstick.java
package cn.javacodes.philosopher;
public class Chopstick {
private boolean taken = false;//判断是此筷子是否被拿起
public boolean isTaken() {
return taken;
}
public synchronized void take() throws InterruptedException { while (taken) {
//如果已被拿起,则等待
wait();
}
//如果没有被拿起,则可以被拿起,并设置taken为true
taken = true;
}
public synchronized void drop() {
//放下筷子之后设置taken为false,并通知其他筷子
taken = false;
notifyAll();
}
}
程序清单1-2 Philosopher.java
package cn.javacodes.philosopher;
import java.util.Random;
import java.util.concurrent.TimeUnit;
public class Philosopher implements Runnable {
private Chopstick left;//左筷子
private Chopstick right;//右筷子
private final int id;//哲学家编号
private final int ponderFactor;//根据这个属性设置思考时间
private Random rand = new Random(250);
public Philosopher(Chopstick left, Chopstick right, int ident, int ponder) {
this.left = left;
this.right = right;
this.id = ident;
this.ponderFactor = ponder;
}
public void run() {
try {
while (true) {
System.out.println(this + " " + "thinking");
Thread.sleep(ponderFactor * rand.nextInt(250)); right.take();
System.out.println(this + " " + "拿右筷子");
left.take();
System.out.println(this + " " + "拿左筷子");
Thread.sleep(ponderFactor * rand.nextInt(250)); System.out.println(this + " " + "吃");
right.drop();
System.out.println(this + " " + "放下右筷子"); left.drop();
System.out.println(this + " " + "放下左筷子"); }
} catch (InterruptedException e) {
System.out.println(this + " 退出 ");
}
}
public String toString() {
return "Phiosopher : " + id;
}
}
程序清单1-3 DeadlockingDiningPhilosophers.java package cn.javacodes.philosopher;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class DeadlockingDiningPhilosophers {
public static void main(String[] args) throws InterruptedException {
int ponder = 5;
int size = 5;
ExecutorService exec = Executors.newCachedThreadPool(); Chopstick[] stick = new Chopstick[size];
for (int i = 0; i < size; i++) {
stick[i] = new Chopstick();
}
for (int i = 0; i < size; i++) {
Philosopher p =
new Philosopher(stick[i], stick[(i + 1) % size], i, ponder);
exec.execute(p);
}
}
}
(2)死锁现象分析
上面的程序清单中所示程序极有可能发生死锁现象,例如当所有的哲学家同时拿起左手的筷子(或同时拿起右手的筷子),那么任何人都不可能再拿起另一只手的筷子,所有哲学家都进入了等待状态(阻塞队列),那么死锁就发生了。