开发者

Java concurrency in practice - Listing 14.9 explanation?

Few listings from JCIP already appeared here. Here is one more (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();
        }
    }
}

Comment in book:

The condition predicate used by await is more complicated than simply testing isOpen. This is needed because if N threads are waiting at the gate at the time it is opened, they should all be allowed to proceed. But, if the gate is opened and closed in rapid succession, all threads might not be released if await examines only isOpen: by the time all the threads receive the notification, reacquire the lock, and emerge from wait, the gate may have closed again. So ThreadGate uses a somewhat more complicated condition predicate: every time the gate is closed, a "generation" counter is incremented, and a thread may pass await if th开发者_JS百科e gate is open now or if the gate has opened since this thread arrived at the gate.

Guys, you may laugh, but I can't get it :). Questions:

  1. explain usage of arrivalGeneration == generation to me in terms of thread T1, T2,... and execution flow.
  2. why passage says every time the gate is closed, a generation counter is incremented? How it happens?

Thanks to everybody!


question #1: Just look at 'generation' as the group you (the thread) belongs to, whole groups are allowed in, so if the door opens the group # is increased, and everyone belonging to the group that was already waiting is allowed in, even if the door is seen as 'locked' again.

question #2: I guess that is an error - it probably should read 'every time the gate is opened ...'


For those, who are interested, seek for answer here.

In this listing the waiting thread T1 is interested if any open event happened during the wait (we do not care whether any close events happened), generation counter helps us to find out this fact.


Question 1:

 while (!isOpen && arrivalGeneration == generation) {
            wait();
        }

if Thread 1 go in await, arrivalGeneration = generation = 1, and then the gate is closed. Thread 1 release the lock,wait(), and then generation should increase, ++generation. generation=2.

when Thread 1 acquire the lock again. arrivalGeneration(=1) dose not equal generation(=2). so Thread 1 do not wait.

Question 2: that mean the door is close, and then the door is open, so generation increase.


I think the key point is "This is needed because if N threads are waiting at the gate at the time it is opened, they should all be allowed to proceed.". To achieve it, only check "!isOpen" is not enough when "the gate is opened and closed in rapid succession". We should have a way to know the gate is once opened even if the gate is closed in rapid succession. After all, the N threads in the previous generation expect to be proceed.

Question 1: The first time all the threads receive the notification, reacquire the lock, and emerge from wait, arrivalGeneration is 0 but generation get new value 1, so N threads are able to proceed.

Question 2: I guess that is an error too.


This is my explanation of arrivalGeneration == generation usage:

Threads are waiting at the gate while both conditions are true: the gate is closed AND the local arrivalGeneration value in their await() methods equals to the current generation value.

Why do we need the second condition here?

Assume, the first group (generation) of participating threads are waiting for the gate to open. Their local arrivalCeneration value is 0 and the current instance generation value is also 0. When the gate starts to open, the generation value is incremented by one and now is 1 (so that the newly arrived participants from now on get their local arrivalGeneration value set to 1). Then, the gate opening method invokes notifyAll(). Our waiting threads from group #0 need some time to wake up. During this time, the gate may be closed again. However, since the second condition arrivalGeneration == generation is now false for group #0, they don't continue to iterate on a while-loop and are allowed to accomplish their passage through the gate (even though the first condition is true, because the gate is officially closed again).

At the same time, those participants from group #1 who didn't manage to slip through the gate before it closed again go on a while-loop to wait because both conditions for them are true: the gate is closed and their local arrivalGeneration value is 1, which is the same as current generation value. Next time, when the gate starts to open again, the generation value will be updated to 2, and thread from group #1 will have the chance to accomplish their passage through the gate, etc...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜