实践中的Java并发 - 清单14.9的解释?

时间:2010-07-14 06:17:57

标签: java concurrency

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使用一个更复杂的条件谓词:每次关闭门时,“生成”计数器递增,如果门现在打开或者门已经打开,线程可以通过等待,因为该线程到达门

伙计们,你们可能会笑,但我无法得到它:)。的的问题:

  1. 根据线程T1,T2,......和执行流程向我解释arrivalGeneration == generation的用法。
  2. 为什么段落every time the gate is closed, a generation counter is incremented?怎么回事?
  3. 感谢大家!

5 个答案:

答案 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 中的线程将有机会完成通过门等...