当前位置: 首页 > 知识库问答 >
问题:

用信号量吃饭

蒋何平
2023-03-14

我正在寻找一种方法来解决用餐哲学家使用信号量的问题,我非常坚持我应该如何去做。我在下面包含了我的代码。

class ChopStick{
    private int count; 
    private boolean inuse; 
    Lock lock = new ReentrantLock(); 
    Condition notInUse = lock.newCondition(); 

    public ChopStick(){
        inuse = false;
    }

    public void pickUp(){
        lock.lock();
        try{
            while(inuse){
                try{
                    notInUse.await();
                }catch(InterruptedException e){}
            }
            inuse = true;
        }finally{lock.unlock();}
    }

    public void putDown(){
        lock.lock();
        try{
            inuse = false; 
            notInUse.signal();
        }finally{lock.unlock();}
    }
}

class Philosopher extends Thread{
    Semaphore sem;
    private ChopStick ch1,ch2; //chopsticks
    private int phil; //philosopher id

    public Philosopher(int p, ChopStick left, ChopStick right, Semaphore s){
        phil = p; 
        ch1 = left; 
        ch2 = right; 
        sem = s;
    }

    public void run() {
        while(true){
            try {
                sem.acquire();
            } catch (InterruptedException e) {}
                think(phil);
                //pickup chopsticks
                ch1.pickUp();
                ch2.pickUp();
                eat(phil);
                //putdown chopsticks
                ch1.putDown();
                ch2.putDown();
                sem.release();
            }
        }

我在想,当一位哲学家用扫描电镜拿起筷子时。acquire()然后使用sem完成。release()但我不确定这是否正确。它是?

编辑,这样我就实现了这个。这似乎有效,但我不确定。

  class ChopStick{
    private Semaphore sem;
    public ChopStick(Semaphore s){
            sem = s;
    }

    public void pickUp(){
            try{
                    sem.acquire();
            }catch(InterruptedException e){}
    }
    public void putDown(){
            sem.release();
    }

共有1个答案

子车凌龙
2023-03-14

与其把信号灯放在哲学家的筷子上,我建议把信号灯放在筷子上;哲学家调用获取左右筷子的信号量,并在完成后释放筷子的信号量。这将取代筷子上的可重入锁。

为了防止死锁,您可以使用try Acquire(int许可,长超时,TimeUnit单位),以便如果Philosher在超时内未能获得其右筷子的信号量,则释放其左筷子的信号量;如果您使用随机超时(例如,在100到500毫秒之间),那么每个哲学家最终都应该取得进展。

编辑:你的新筷子代码有死锁的风险-所有哲学家拿起他们的左筷子,然后永远等待他们的右筷子自由。tryAcquire将允许哲学家在超时后无法获取右筷子时释放其左筷子,这将允许哲学家在其左侧继续。

class ChopStick{
  private static Random random = new Random();

  // initialize with one permit
  private Semaphore sem = new Semaphore(1);

  public boolean pickUp(){
    try {
      // wait between 100 and 500 milliseconds
      return sem.tryAcquire(1, random.nextInt(400) + 100, TimeUnit.MILLISECONDS);
    } catch(InterruptedException e) {
      return false;
    }
  }

  public void putDown(){
    sem.release();
  }
}

class Philosopher extends Thread {
  public void run() {
    while(true){
      think(phil);
      doEat();
    }

  private void doEat() {
    if(ch1.pickup()) {
      if(ch2.pickup()) {
        eat(phil);
        ch1.release();
        ch2.release();
      else {
        ch1.release();
        doEat();
      }
    else {
      doEat();
    }
  }
}

 类似资料:
  • 首先想到的问题是,为什么我们需要信号量? 一个简单的答案,以保护多个进程共享的关键/共同区域。 假设多个进程正在使用相同的代码区域,如果所有人都想并行访问,那么结果是重叠的。 例如,多个用户仅使用一台打印机(通用/关键部分),例如个用户,同时给予个作业,如果所有作业并行启动,则一个用户输出与另一个用户输出重叠。 因此,我们需要使用信号量来保护这个信号,即当一个进程正在运行时锁定关键部分,并在完成时

  • 信号量 信号量是一种同步互斥机制的实现,普遍存在于现在的各种操作系统内核里。相对于spinlock 的应用对象,信号量的应用对象是在临界区中运行的时间较长的进程。等待信号量的进程需要睡眠来减少占用 CPU 的开销。参考教科书“Operating Systems Internals and Design Principles”第五章“同步互斥”中对信号量实现的原理性描述: struct semaph

  • 一个线程发送信号量,另外一个线程接收信号量 一个线程发送信号量,另外一个线程接收信号量 源码/* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2018-08-24 yangjie

  • 信号量接口 结构体 struct   rt_semaphore   信号量控制块 更多...   类型定义 typedef struct rt_semaphore *  rt_sem_t   信号量类型指针定义   函数 rt_err_t  rt_sem_init (rt_sem_t sem, const char *name, rt_uint32_t value, rt_uint8_t flag

  • 信号量 这是本章的第三部分 chapter,本章描述了内核中的同步原语,在之前的部分我们见到了特殊的 自旋锁 - 排队自旋锁。 在更前的 部分 是和 自旋锁 相关的描述。我们将描述更多同步原语。 在 自旋锁 之后的下一个我们将要讲到的 内核同步原语是 信号量。我们会从理论角度开始学习什么是 信号量, 然后我们会像前几章一样讲到Linux内核是如何实现信号量的。 好吧,现在我们开始。 介绍Linux

  • 该函数的操作对象为信号量,而非信号量集合。这是一个原子操作。 为semaphore operate的缩写 函数原型 #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semop(int semid, struct sembuf *sops, unsigned nsops); int semtimedop(int