Java中的信号量问题
我试图学习这个问题中信号量的基本jist。现在,我有一个类筷子数组,每个筷子都有一个带有1个可用许可证的信号灯: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
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关键字。很好的发现。看起来这是一个家庭作业的一部分,他有一些很酷的要求,说他必须使用信号量。你可以做的另一件事是让筷子延伸信号量(或锁)。:)尽管直接使用它不会给你带来任何好处。