JCIP的几个列表已经出现在这里。这是另外一个(orig. code):
public class ThreadGate { private boolean isOpen; private int generation; public synchronized void close() { isOpen = false; } public synchronized void open() { ++generation; isOpen = true; notifyAll(); } public synchronized void await() throws InterruptedException { int arrivalGeneration = generation; while (!isOpen && arrivalGeneration == generation) { wait(); } } }
书评:
await使用的条件谓词比简单地测试isOpen更复杂。这是必要的,因为如果N个线程在打开时在门口等待,则应该允许所有线程继续进行。但是,如果门快速连续打开和关闭,如果await仅检查isOpen,则所有线程可能都不会被释放:当所有线程收到通知,重新获取锁定并从等待中退出时,门可能再次关闭。因此,ThreadGate使用一个更复杂的条件谓词:每次关闭门时,“生成”计数器递增,如果门现在打开或者门已经打开,线程可以通过等待,因为该线程到达门
伙计们,你们可能会笑,但我无法得到它:)。的的问题:
arrivalGeneration == generation
的用法。every time the gate is closed, a generation counter is incremented
?怎么回事?感谢大家!
答案 0 :(得分:1)
问题#1:只要看一下'代'是你(线程)所属的组,允许整个组进入,所以如果门打开,组#会增加,而每个人都属于已经是等待被允许进入,即使门再被视为“锁定”。
问题#2:我猜这是一个错误 - 它可能应该是'每次门打开时 ......'
答案 1 :(得分:1)
对于那些有兴趣的人,请寻求答案here。
在这个列表中,如果在等待期间发生了任何打开事件,等待线程T1感兴趣(我们不关心是否发生任何关闭事件),generation
计数器帮助我们找出这个事实。
答案 2 :(得分:0)
问题1:
while (!isOpen && arrivalGeneration == generation) {
wait();
}
如果线程1进入等待,arrivalGeneration = generation = 1,则关闭门。线程1释放锁定,wait(),然后生成应该增加,++生成。代= 2。
当线程1再次获得锁定时。到货生成(= 1)剂量不等于生成(= 2)。 所以线程1不等待。
问题2: 这意味着门是关闭的,然后门打开,所以增加了一代。
答案 3 :(得分:0)
我认为关键点是“这是必要的,因为如果N个线程在打开时在门口等待,它们都应该被允许继续。”要实现它,只有当“门快速连续打开和关闭”时才检查“!isOpen”是不够的。我们应该知道即使闸门快速连续关闭,闸门也会被打开。毕竟,前一个代中的N个线程希望继续。
问题1:所有线程第一次收到通知,重新获取锁定,并从等待中退出,arrivalGeneration为0但生成获得新值1,因此N个线程能够继续。
问题2:我猜这也是一个错误。
答案 4 :(得分:0)
这是我对arrivalGeneration == generation
用法的解释:
当两个条件都成立时,线程在门口等待:门关闭,并且其arrivalGeneration
方法中的本地await()
值等于当前generation
的值。
为什么我们在这里需要第二个条件?
假定,参与线程的第一组(生成)正在等待门打开。它们的本地arrivalCeneration
值为0
,当前实例generation
的值为0
。当门开始打开时,generation
的值将增加一个,现在为1
(这样,从现在开始,新到达的参与者将其本地arrivalGeneration
的值设置为{{1 }})。然后,门打开方法调用1
。来自 group#0 的等待线程需要一些时间才能唤醒。在此期间,门可能会再次关闭。但是,由于第二个条件notifyAll()
对于 group#0 现在为false,因此它们不会继续在while循环中进行迭代,并且被允许完成通过门的操作(即使尽管第一个条件为真,因为门再次正式关闭)。
与此同时,来自组#em 的那些未能在大门再次关闭之前滑过大门的参与者进入了while循环等待,因为他们的两个条件都成立:门已关闭,其本地arrivalGeneration == generation
值为arrivalGeneration
,与当前1
值相同。下次,当门再次开始打开时,generation
的值将更新为generation
,并且 group#1 中的线程将有机会完成通过门等...