Требуется ли ключевое слово volatile для полей, доступных через ReentrantLock?
Мой вопрос относится к тому, что использование ReentrantLock гарантирует видимость поля в том же отношении, что и синхронизированное ключевое слово.
Например, в следующем классе A поле sharedData не обязательно должно быть объявлено volatile при использовании ключевого слова synchronized.
class A
{
private double sharedData;
public synchronized void method()
{
double temp = sharedData;
temp *= 2.5;
sharedData = temp + 1;
}
}
В следующем примере, используя ReentrantLock, нужно ли ключевое слово volatile в нужном поле?
class B
{
private final ReentrantLock lock = new ReentrantLock();
private volatile double sharedData;
public void method()
{
lock.lock();
try
{
double temp = sharedData;
temp *= 2.5;
sharedData = temp + 1;
}
finally
{
lock.unlock();
}
}
}
Я знаю, что использование ключевого слова volatile в любом случае, скорее всего, приведет к незначительному результату производительности, но я все равно хотел бы правильно кодировать.
Ответы
Ответ 1
Это безопасно без волатильности. ReentrantLock
реализует Lock
, а docs для Lock
включает в себя следующее:
Все реализации Lock
должны обеспечивать соблюдение такая же синхронизация памяти семантика, предоставляемая встроенным блокировка монитора, как описано в разделе "Java" Спецификация языка, третье издание (17.4 Модель памяти):
- Успешная операция
Lock
имеет такие же эффекты синхронизации памяти, как и успешное действие Lock
. - Успешный Операция
unlock
имеет одинаковую память эффекты синхронизации как успешное действие unlock
.