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. Ссылка поможет!

Ссылка: http://rsim.cs.illinois.edu/Pubs/08PLDI.pdf

2 ответа

Решение

Из Javadoc для блокировки:

Неудачные операции блокировки и разблокировки и повторные операции блокировки / разблокировки не требуют каких-либо эффектов синхронизации памяти.

Если при попытке блокировки удастся взять блокировку, она будет синхронизирована с предыдущей блокировкой T1. Через семантику блокировки мы знаем, что не может быть предыдущей блокировки T1, когда мы входим в цикл. Таким образом, если мы войдем в цикл, связь с T1 не синхронизируется.

Если (или когда) попытка блокировки завершается неудачно, связь с T1 не синхронизируется. По крайней мере, если предположить, что trylock неудача - это "неудачная операция блокировки", как подсказывает ответ jtahlborn.

Поэтому, в любом случае, между присваиванием и утверждением нет отношения "происходит до". Таким образом, у нас есть гонка данных, и значение х может быть или не быть 42.

Я не могу найти ничего явного, что Java trylock может быть "ложным". Тем не менее, этот пример имеет поддельное поведение в Java.

Тем не менее, JavaDoc для trylock говорит

Получает блокировку, если она доступна, и немедленно возвращает значение true.

но языковая спецификация превосходит JavaDoc по моему мнению.

Другие вопросы по тегам