描述:五个哲学家围着一张圆桌,每个哲学家面前放着食物。哲学家的生活有两种交替活动:吃饭思考。当一个哲学家吃饭时,需要先拿起自己左右两边的两根筷子,并且一次只能拿起一根筷子。
解决1:至多只允许四个哲学家同时进餐,以保证至少有一个哲学家能够进餐,最终总会释放出他所使用过的两支筷子,从而可使更多的哲学家进餐。设置一个信号量room,使其初始值为4,在哲学家拿起他左边的筷子之前,先对信号量做一次P操作,从而当第五位哲学家去拿做筷子时,room = -1被阻塞,避免了死锁问题。然后当哲学家放下他左边的筷子的时候,就对r做一次V操作。
semaphore chopstick[5]={1,1,1,1,1};
semaphore count=4; // 设置一个count,最多有四个哲学家可以进来
void philosopher(int i)
{
while(true)
{
think();
wait(count); //请求进入房间进餐 当count为0时 不能允许哲学家再进来了
wait(chopstick[i]); //请求左手边的筷子
wait(chopstick[(i+1)%5]); //请求右手边的筷子
eat();
signal(chopstick[i]); //释放左手边的筷子
signal(chopstick[(i+1)%5]); //释放右手边的筷子
signal(count); //退出房间释放信号量
}
}
解决2:仅当哲学家的左右两支筷子都可用时,才允许他拿起筷子进餐
public class ThreadTest{
public static void main(String[] args) {
Fork fork = new Fork();
new Philosopher("0", fork).start();
new Philosopher("1", fork).start();
new Philosopher("2", fork).start();
new Philosopher("3", fork).start();
new Philosopher("4", fork).start();
}
}
class Philosopher extends Thread{
private String name;
private Fork fork;
public Philosopher(String name, Fork fork) {
super(name);
this.name = name;
this.fork = fork;
}
@Override
public void run() {
while (true){
thinking();
fork.takeFork();
eating();
fork.putFork();
}
}
public void eating(){
System.out.println("I am Eating:"+name);
try {
sleep(1000);//模拟吃饭,占用一段时间资源
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void thinking(){
System.out.println("I am Thinking:"+name);
try {
sleep(1000);//模拟思考
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public Fork getFork() {
return fork;
}
public void setFork(Fork fork) {
this.fork = fork;
}
}
class Fork{
/*5只筷子,初始为都未被用*/
private boolean[] used={false,false,false,false,false,false};
public synchronized void takeFork(){
String name = Thread.currentThread().getName();
int i = Integer.parseInt(name);
while(used[i] || used[(i+1)%5]){
try {
wait();//如果左右手有一只正被使用,等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
used[i ]= true;
used[(i+1)%5]=true;
}
public synchronized void putFork(){
String name = Thread.currentThread().getName();
int i = Integer.parseInt(name);
used[i]= false;
used[(i+1)%5]=false;
notifyAll();//唤醒其他线程
}
}
交替打印奇偶
public class WaitNotify {
// 状态锁
private static Object lock = new Object();
private static Integer i = 0;
public void odd() {
while (i < 10) {
synchronized (lock) {
if (i % 2 == 1) {
System.out.println(Thread.currentThread().getName() + " - " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
lock.notify();
} else {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public void even() {
while (i < 10) {
synchronized (lock) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + " - " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
lock.notify();
} else {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public static void main(String[] args) {
WaitNotify waitNotify = new WaitNotify();
Thread t1 = new Thread(() -> waitNotify.odd(), "线程1");
Thread t2 = new Thread(() -> waitNotify.even(), "线程2");
t1.start();
t2.start();
}
}