Флаг одновременной блокировки в Java - PullRequest
2 голосов
/ 21 октября 2019

Я иногда пишу код вроде:

Метод 1:

synchronized (someMonitor) {
    newInfo = true;
    someMonitor.notifyAll();
}

Метод 2:

synchronized (someMonitor) {
    while (!newInfo) {
        someMonitor.wait();
    }
    newInfo = false;
}

Я думаю, что в объекте параллелизма более высокого уровняAPI, чтобы справиться с этим. Он должен работать следующим образом:

Метод 1:

ensureFlagRaised();

Метод 2:

blockUntilFlagRaisedThenLowerFlag();

Я мог бы использовать BlockingQueue с емкостью 1 для вызова неблокирующего предложения(dummyElement) и блокирующий дубль (). Но это похоже на злоупотребление этим классом.

Есть ли более чистые решения?

1 Ответ

4 голосов
/ 21 октября 2019

Это можно сделать несколькими способами.

Наиболее прямой заменой будет переключение с использованием Lock и Signal, что близко имитирует механизм synchronized/wait/notify.

Но для простого флага, самый простой подход - это Семафор . При этом ваш пример кода может выглядеть следующим образом:

Semaphore s = new Semaphore(0, true); // No permits to start with, acquire will block

// Producer loop
makeNewDataAvailable();
s.release();  // Raise "flag" to indicate new info
possiblyDoSomethingUseful();
s.acquire();  // A fair semaphore, so waiting threads get the permit

// Consumer loop
s.acquire();  // Blocks until "flag" raised, then acquires it
processNewData();
s.release();  // Pass the permit back to thread 1

Но Semaphore требует от вас правильного планирования логики, в противном случае вы можете оказаться в тупике.

AСитуация с производителем / потребителем решается лучше с помощью других механизмов, поскольку, как вы видите, код может выглядеть запутанным, и вам необходимо отслеживать, кто звонит acquire/release и когда. Приведенный выше код может быть лучше реализован, например, с помощью Exchanger :

Exchanger<String> e = new Exchanger<>();

// Producer loop
e.exhange(generateNewData());  // Ignore consumer's response

// Consumer loop
processData(e.exchange(null)); // Get data, send dummy back
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...