【发布时间】:2013-10-11 10:19:24
【问题描述】:
我正在尝试,但是有一个问题: 在 wiki 中,该算法的第三点说:
当一个有叉子的哲学家收到请求消息时,如果叉子是干净的,他会保留叉子,但如果叉子脏了就放弃。如果他把叉子送过来,他会在这样做之前清理叉子
我试图理解为什么这不会导致死锁?如果一位哲学家有一个干净的叉子,并等待从邻近的餐厅/哲学家那里得到另一个干净的叉子,而后者也在等待叉子,这可能会累积成僵局,对吗?一位哲学家总是在等待另一位哲学家的分叉?
ps:我是线程和并发的新手,把它当作一个学习项目。
编辑:提供分叉的实际位置,发布此内容以询问分叉是否应该是可变的。 pLeft , pRight 是左右哲学家,fLeft 和 fRight 是左右叉子。
private Fork giveFork(Philosopher diner) {
Fork forkToGive;
if (this.pLeft.equals(diner)) {
// give left fork to left philosopher
if (this.fLeft.isClean)
forkToGive = null; // don't give
else {
forkToGive = new Fork(this.fLeft.id, true); // give the fork
}
} else if (diner.pRight.equals(this)) {
// give right fork to right philosopher
if (this.fRight.isClean)
forkToGive = null;
else {
forkToGive = new Fork(this.fRight.id, true);
}
} else {
// default value , i'm not yet sure if this code
// can be theoretically reached
forkToGive = null;
}
return forkToGive;
}
我还没有弄清楚在哪里同步它,但我觉得仍然需要同步。就像当两个用餐者时,说第一个和第三个向第二个哲学家要叉子。
【问题讨论】:
-
描述说如果叉子脏了,哲学家就放弃叉子,一开始所有叉子都是脏的。
-
是的,但我不明白如何初始化“所有”叉子?我有收藏叉子吗?并随着时间的推移将它们更改为清洁/肮脏?我试图尽可能多地保持不变性,所以我决定不保留一组可变分叉,并在需要时创建并提供新的干净分叉。
-
forks 是共享资源并且必须是可变的(否则,不需要整个协议,因为每个哲学家都可以得到干净的 fork 对)。通常,所有花哨的同步协议都需要管理跨进程/线程共享的可变数据,如果您的数据是不可变的(纯粹是功能性的),则无需担心同步。
-
从给脏叉子的哲学家的观点来看,他必须先清理它,现在假设我创建了脏叉子的副本,只让它干净,然后替换脏叉子有了新的干净的,仍然有一个叉子,并且还有不变性..
-
假设
giveFork()由提供fork 的哲学家执行,您需要同步才能将生成的fork 返回给请求者(例如,通过wait()/notifyAll())。但是由于创建了分叉,这段代码比必要的更复杂。其实不需要专门的Fork类,你只需要数组ForkState forks[philosophersNr],并让你的各方在上面同步。
标签: algorithm concurrency dining-philosopher