Я читал о некоторых деталях реализации ReentrantLock в «Java Параллелизм на практике», раздел 14.6.1, и что-то в аннотации заставляет меня путать:Как выполняется переписывание текущей переменной потока в ReentrantLock.Sync?
Поскольку защищенные методы государственной манипуляции имеют семантика памяти волатильного чтения или записи и ReentrantLock осторожно, чтобы читал поле владельца только после вызова getState и написал его только до вызова setState, ReentrantLock может копировать в семантику памяти состояния синхронизации и, таким образом, избегать дополнительной синхронизации. Раздел 16.1.4.
код, который он ссылается на:
protected boolean tryAcquire(int ignored) {
final Thread current = Thread.currentThread();
int c = getState();
if (c ==0) {
if (compareAndSetState(0, 1)) {
owner = current;
return true;
}
} else if (current == owner) {
setState(c+1);
return true;
}
}
И я считаю, что это упрощенный код nonfirTryAcquire
в ReentrantLock.Sync
.
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
Итак, озадачивает часть, как установка owner
, которая является всего лишь обычная переменная экземпляра в AbstractOwnableSynchronizer
, становится видимым else if (current == owner)
в других потоках. Действительно, чтение owner
происходит после вызова getState()
(а state
- это volatile
квалифицированная переменная AQS
), но после установки owner
ничего нет (можно установить семантику синхронизации). Происходит гонка данных?
Ну, в свете власти этой книги и тщательно протестированного кода, две возможности прийти на ум:
The полный барьер (будь то mfence или «lock'ed инструкцию) до настройка
owner = current
делает скрытую работу. Но из того, что я узнал из нескольких известных статей, полный барьер больше заботится о писаниях перед ним, а также о чтениях после него. Ну, если эта возможность верна, то некоторые предложения в «JCIP» могут быть неправильно указаны.Я заметил, что «географически»
setState(c+1)
действительно приходит послеowner = current
в фрагменте кода, хотя он находится в другой ветке if-else. Если, как говорят комментарии, это правда, означает ли это, что барьер, вставленныйsetSate(c+1)
, может наложить семантику синхронизации наowner = current
в другую ветку?
Я новичок в этой области, а также несколько больших блоги мне очень помогают в понимании того, что никогда, лежащей в основе виртуальной машины Java (без заказа):
- http://mechanical-sympathy.blogspot.com/
- http://preshing.com/
- http://bartoszmilewski.com
- http://psy-lob-saw.blogspot.com/
, а также всегда великолепный: http://g.oswego.edu/dl/jmm/cookbook.html
После выполнения домашней работы и поиска в Интернете я не могу прийти к удовлетворительному выводу.
Простите меня, если это слишком многословно или неясно (английский не мой родной язык). Пожалуйста, помогите мне в этом, все, что связано, оценено.
Возможно, вас заинтересует «Ракурс синхронизации java.util.concurrent» Дуга Ли. http://gee.cs.oswego.edu/dl/papers/aqs.pdf – ewernli
Это один из немногих за пределами меня сейчас, я думаю, но я попробую. Спасибо, @ewernli. И благодаря rolfl за то, что вы меня выпустили, я никогда не должен забывать большую (большую?) Картину. – DarKeViLzAc