哲學家就餐問題-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*/