代码之家  ›  专栏  ›  技术社区  ›  Logan Serman

Java中的信号量问题与餐饮哲学家

  •  5
  • Logan Serman  · 技术社区  · 17 年前

    public class Chopstick
    {
        Thread holder = null;
        private Semaphore lock = new Semaphore(1);
    
        public synchronized void take() throws InterruptedException
        {
            this.lock.acquire();
            holder = Thread.currentThread();
    
        }
    
        public synchronized void release()
        {   
            this.lock.release();
            holder = null;
        }
    }
    

    public synchronized void conditionalRelease()
    {
        if (holder == Thread.currentThread())
        {
            holder = null;
            this.lock.release();
        }
    }
    

    以下是Philosopher类中在随机时间后释放筷子的代码:

    System.out.println(this.name + " is eating");
    Thread.sleep(this.getRandTime());
    System.out.println(this.name + " has finished eating");
    
    rightChopstick.release();
    System.out.println(this.name + " has released the right chopstick");
    leftChopstick.release();
    System.out.println(this.name + " has released the left chopstick");
    

    例如,我的程序确实输出“Philosopher 0已吃完”,并继续执行。另外两行永远不会输出,所以很明显我的发布方式出了问题。

    任何帮助都将不胜感激。

    5 回复  |  直到 17 年前
        1
  •  8
  •   Tim Frey    17 年前

    我会从你的方法签名中删除“synchronized”关键字。您正在使用外部锁定机制(在本例中为信号量)。关键字“synchronized”试图使用对象自己的互斥体获取锁。您现在锁定了2个资源,我怀疑这可能会导致死锁。

        2
  •  1
  •   Johannes Weiss    17 年前

    问题是,当thread1有一个特定的筷子,而另一个试图得到相同的筷子时,它会在 take() -在线方法 this.lock.acquire(); 但它会 释放对象本身上的监视器。

    如果现在螺纹1试图松开筷子,它将无法进入 release() take() 这是一个僵局

        4
  •  1
  •   captainMorgan    9 年前

    public class Chopstick {
    private boolean inuse;
    Semaphore sem;
    
    public Chopstick(){
    
        inuse = false;
        sem = new Semaphore(1);
    }
    public void pickUp()
    {
        try
        {
            while(inuse)
            {
                try
                {
                    sem.acquire();
    
                }
                catch(InterruptedException e) {}
            }
            inuse = true;
        }catch(Exception e){}
    }
    public void putDown()
    {
        try
        {
            inuse = false;
            sem.release();
    
        }
        catch (Exception e){}
    }
    

    }

        5
  •  0
  •   Mak    12 年前

    public synchronized void startEating() {
        leftChopstick.acquire();
        rightChopstick.acquire();
    }
    
    public void finishEating(int id) {
        leftChopstick.release();
        rightChopstick.release();
    }