Параллелизм Java на практике - объяснение листинга 14.9? - PullRequest
4 голосов
/ 14 июля 2010

Несколько списков от JCIP уже появилось здесь. Вот еще один ( код оригинала ):

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. объясните мне использование arrivalGeneration == generation в терминах потока T1, T2, ... и потока выполнения.
  2. почему в отрывке написано every time the gate is closed, a generation counter is incremented? Как это происходит?

Спасибо всем!

Ответы [ 4 ]

1 голос
/ 14 июля 2010

Для тех, кто заинтересован, ищите ответ здесь .

В этом списке ожидающий поток T1 интересуется, произошло ли какое-либо открытое событие во время ожидания (нам все равнолюбые близкие события произошли), generation counter помогает нам выяснить этот факт.

1 голос
/ 14 июля 2010

вопрос № 1: Просто посмотрите на «генерацию» как группу, к которой вы (поток) принадлежите, в нее могут входить целые группы, поэтому, если дверь открывается, число # увеличивается, и каждый член группы, которая уже быладопускается ожидание, даже если дверь снова считается «запертой».

вопрос № 2: Я думаю, что это ошибка - она, вероятно, должна читать «каждый раз, когда ворота открыты * 1004»* ... '

0 голосов
/ 28 ноября 2016

Я думаю, что ключевым моментом является «Это необходимо, потому что, если N потоков ожидают у ворот в момент их открытия, им всем должно быть разрешено продолжить .». Чтобы достичь этого, недостаточно только проверить «! IsOpen», когда «ворота открываются и закрываются в быстрой последовательности». У нас должен быть способ узнать, что ворота однажды открыты, даже если ворота закрываются в быстрой последовательности. В конце концов, N потоков в предыдущем поколении ожидают продолжения.

Вопрос 1. В первый раз, когда все потоки получают уведомление, повторно получают блокировку и выходят из режима ожидания, destinationGeneration равен 0, но генерация получает новое значение 1, поэтому N потоков могут продолжить.

Вопрос 2. Думаю, это тоже ошибка.

0 голосов
/ 23 октября 2016

Вопрос 1:

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

, если поток 1 заходит в ожидание, прибытие поколения = поколение = 1, а затем ворота закрываются.Поток 1 снимает блокировку, wait (), а затем увеличивается генерация, генерация ++.поколение = 2.

, когда Поток 1 снова получает блокировку.прибытие поколения (= 1) доза не равна генерации (= 2).поэтому поток 1 не ждет.

Вопрос 2: это означает, что дверь закрыта, а затем дверь открыта, поэтому генерация увеличивается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...