信号量问题Java与哲学家就餐
-
03-07-2019 - |
题
我努力学习基本的脸谱的一个信号在餐哲学家的问题。现在,我有一系列类筷子,并且每个筷子有一个信号量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;
}
}
在座的变量是用于一个功能,我不知道我需要的:
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()
-method等待 this.lock.acquire() ;
但 NOT 会释放对象本身的监视器。
如果现在thread1试图释放筷子,它就无法进入 release()
-method,因为它仍然被另一个在 take()
中等待的线程锁定。这是一个僵局
这似乎有点混淆了你们两个都锁上的筷子并让它保持一个信号量的尺寸1.通常一个信号提供的门票资源和如果你只有一票,这是有效地相互排斥而是相同的锁定(不论是一个同步块或锁定对象)。你可能会考虑实际使筷子的锁定对象本身。
我做了一篇博客上用餐的哲学家在Java一会儿回来如果你有兴趣,虽然它真正关心如何避免僵局使用的其他策略。
确保没有使用任何锁定或synchronized关键字。筷子下面的代码对我来说很好。不是专业人士,但必须给你一些想法;
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){}
}
}
Philospher在开始进食之前需要锁定两个chosticks并且先将leftone先取出然后等待,所以开始进食所以start方法应该同步。 以下方法将使其工作:
public synchronized void startEating() {
leftChopstick.acquire();
rightChopstick.acquire();
}
public void finishEating(int id) {
leftChopstick.release();
rightChopstick.release();
}