用java编程实现哲学家进餐问题
时间: 2024-02-28 15:57:12 浏览: 75
Java模拟死锁发生之演绎哲学家进餐问题案例详解
哲学家进餐问题是一个经典的多线程同步问题,本质上是一种资源竞争问题。以下是用Java编程实现哲学家进餐问题的示例代码:
```
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class DiningPhilosophers {
private static final int NUM_PHILOSOPHERS = 5;
private static final int NUM_FORKS = 5;
public static void main(String[] args) {
Philosopher[] philosophers = new Philosopher[NUM_PHILOSOPHERS];
Object[] forks = new Object[NUM_FORKS];
// 初始化叉子对象
for (int i = 0; i < NUM_FORKS; i++) {
forks[i] = new Object();
}
// 创建哲学家对象并启动线程
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
Object leftFork = forks[i];
Object rightFork = forks[(i + 1) % NUM_FORKS];
// 最后一个哲学家的左右叉子需要交换
if (i == NUM_PHILOSOPHERS - 1) {
philosophers[i] = new Philosopher(rightFork, leftFork);
} else {
philosophers[i] = new Philosopher(leftFork, rightFork);
}
new Thread(philosophers[i], "哲学家 " + (i + 1)).start();
}
}
}
class Philosopher implements Runnable {
private Object leftFork;
private Object rightFork;
private Lock lock = new ReentrantLock();
public Philosopher(Object leftFork, Object rightFork) {
this.leftFork = leftFork;
this.rightFork = rightFork;
}
@Override
public void run() {
try {
while (true) {
// 尝试获取左叉子
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + " 拿起左边的叉子");
// 尝试获取右叉子
synchronized (rightFork) {
System.out.println(Thread.currentThread().getName() + " 拿起右边的叉子,开始进餐");
Thread.sleep(1000); // 模拟进餐时间
}
} finally {
// 放下左叉子
System.out.println(Thread.currentThread().getName() + " 放下左边的叉子");
lock.unlock();
}
// 放下右叉子
System.out.println(Thread.currentThread().getName() + " 放下右边的叉子,开始思考");
Thread.sleep(1000); // 模拟思考时间
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
```
在这个示例代码中,每个哲学家都是一个线程。每个哲学家需要持有两个叉子才能进餐。为了避免死锁,我们使用了一个锁对象来保证每个哲学家只能拿起一只叉子,等到拿到第二只叉子才能进餐。同时,我们将每个叉子都作为一个对象来进行互斥访问,避免了多个哲学家同时竞争同一个叉子的情况。
阅读全文