哲学家问题

描述:五个哲学家围着一张圆桌,每个哲学家面前放着食物。哲学家的生活有两种交替活动:吃饭思考。当一个哲学家吃饭时,需要先拿起自己左右两边的两根筷子,并且一次只能拿起一根筷子。

解决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();
 	 }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值