Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ember.js/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的信号量问题_Java_Multithreading_Locking_Semaphore - Fatal编程技术网

Java中的信号量问题

Java中的信号量问题,java,multithreading,locking,semaphore,Java,Multithreading,Locking,Semaphore,我试图学习这个问题中信号量的基本jist。现在,我有一个类筷子数组,每个筷子都有一个带有1个可用许可证的信号灯: public class Chopstick { Thread holder = null; private Semaphore lock = new Semaphore(1); public synchronized void take() throws InterruptedException { this.lock.acquir

我试图学习这个问题中信号量的基本jist。现在,我有一个类筷子数组,每个筷子都有一个带有1个可用许可证的信号灯:

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;
    }
}
holder变量用于我不确定需要的函数:

public synchronized void conditionalRelease()
{
    if (holder == Thread.currentThread())
    {
        holder = null;
        this.lock.release();
    }
}
该程序编译并运行,但似乎在释放筷子时遇到了一些问题。有时候,筷子会松开,有时候不会。如果他们不发布,当所有的筷子都被拿走,一位哲学家饿了,程序最终会挂断

以下是哲学家类中的代码,用于在随机时间后释放筷子:

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");
例如,我的程序输出“哲学家0已经吃完了”,并继续执行。另外两行永远不会输出,所以很明显我释放的方式有问题


非常感谢您的帮助。

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

问题是,当thread1有一个特定的筷子,而另一个尝试获取相同的筷子时,它将在
take()
-方法中等待
this.lock.acquire()但它将而不是释放对象本身上的监视器


如果thread1现在试图释放筷子,它将无法进入
release()
-方法,因为它仍然被等待
take()
的另一个线程锁定。这是一个死锁

看起来有点让人困惑,你们都把筷子锁上了,还让它拿着一个1号的信号灯。通常,信号量向资源提供票证,如果您只有一个票证,则实际上是互斥,这与锁(同步块或锁对象)相同。你可以考虑让筷子本身成为锁对象。 如果你感兴趣的话,我在前一段时间写了一篇关于Java中的用餐哲学家的博客,尽管它实际上是关于如何通过使用其他策略避免死锁


在开始进食之前,Philospher需要获得两个食物棒上的锁,并将首先拾取左边的食物棒,然后等待右边的食物棒,因此开始进食,所以启动方法应同步。 以下方法将使其起作用:

public synchronized void startEating() {
    leftChopstick.acquire();
    rightChopstick.acquire();
}

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

确保没有使用任何锁定或同步关键字。下面的代码对我来说很有用。。不是专业人士,但必须给你一些想法

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){}
}

}

Ha!那正是它的原委。。。我必须为赋值实现这两种不同的方法,我为第一种方法复制粘贴的代码,但忘记删除synchronized关键字。很好的发现。看起来这是一个家庭作业的一部分,他有一些很酷的要求,说他必须使用信号量。你可以做的另一件事是让筷子延伸信号量(或锁)。:)尽管直接使用它不会给你带来任何好处。