Позволяет сказать, что я взаимодействую с системой, которая имеет два увеличивающих счетчика, которые зависят друг от друга (эти счетчики никогда не будут уменьшаться): int totalFoos; // barredFoos plus nonBarredFoos int barredFoos;Основная проблема с потоками Java
У меня также есть два способа: int getTotalFoos(); // В основном сетевой вызов localhost int getBarredFoos(); // В основном сетевой вызов localhost
Эти два счетчика сохраняются и увеличиваются по коду, к которому у меня нет доступа. Предположим, что он увеличивает оба счетчика на альтернативный поток, но в потокобезопасном режиме (т. Е. В любой момент времени два счетчика будут синхронизироваться).
Каков наилучший способ получить точный счет как запрещенных, так и nonBarredFoos в один момент времени?
Полностью наивная реализация:
int totalFoos = getTotalFoos();
int barredFoos = getBarredFoos();
int nonBarredFoos = totalFoos - barredFoos;
Это вопрос о том, что система может инкремент обоих счетчиков между двумя вызовами метода, а затем мои две копии будет синхронизирован и barredFoos
будет иметь значение больше, чем когда было получено totalFoos
.
Basic перепроверены реализация:
while (true) {
int totalFoos = getTotalFoos();
int barredFoos = getBarredFoos();
if (totalFoos == getTotalFoos()) {
// totalFoos did not change during fetch of barredFoos, so barredFoos should be accurate.
int nonBarredFoos = totalFoos - barredFoos;
break;
}
// totalFoos changed during fetch of barredFoos, try again
}
Это должно работать в теории, но я не уверен, что JVM гарантирует, что это то, что на самом деле происходит на практике один раз оптимизации и такой учитывается. Пример этих проблем см. В разделе http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html (ссылка через Ромена Мюллера).
Учитывая методы, которые у меня есть, и предположение выше, что счетчики фактически обновляются вместе, существует ли способ гарантировать, что мои копии двух счетчиков синхронизированы?
Вы не должны полагаться на перепроверить, чтобы правильно работать в Java: HTTP: // www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html – Romain
@RomainMuller благодарит за ссылку. Это именно то, о чем я говорил в своей озабоченности по поводу последнего примера выше. –
Я полностью отметил эту статью в первый раз, когда я ее видел ... В Java есть много очень распространенных ошибок, которые почти все совершают, не зная, что зло скрывается в темноте ... – Romain