JMM и нежелательное использование trylock
Нежелательное использование трилока
T1 T2
x = 42; while (lock.trylock())
lock.lock(); lock.unlock();
assert(x == 42);
В java и C++ модели памяти позволяют x=42 перемещаться после блокировки (1). И поэтому assert может потерпеть неудачу в потоке T2. Поэтому в модели памяти C++ они определили, что поведение флокирования trylock может быть ложным. Но я не нашел, каковы спецификации для trylock в модели памяти Java.Можно утверждать, что в потоке 2 гарантированно перейти в Java. Ссылка поможет!
2 ответа
Из Javadoc для блокировки:
Неудачные операции блокировки и разблокировки и повторные операции блокировки / разблокировки не требуют каких-либо эффектов синхронизации памяти.
Если при попытке блокировки удастся взять блокировку, она будет синхронизирована с предыдущей блокировкой T1. Через семантику блокировки мы знаем, что не может быть предыдущей блокировки T1, когда мы входим в цикл. Таким образом, если мы войдем в цикл, связь с T1 не синхронизируется.
Если (или когда) попытка блокировки завершается неудачно, связь с T1 не синхронизируется. По крайней мере, если предположить, что trylock
неудача - это "неудачная операция блокировки", как подсказывает ответ jtahlborn.
Поэтому, в любом случае, между присваиванием и утверждением нет отношения "происходит до". Таким образом, у нас есть гонка данных, и значение х может быть или не быть 42.
Я не могу найти ничего явного, что Java trylock
может быть "ложным". Тем не менее, этот пример имеет поддельное поведение в Java.
Тем не менее, JavaDoc для trylock говорит
Получает блокировку, если она доступна, и немедленно возвращает значение true.
но языковая спецификация превосходит JavaDoc по моему мнению.