1

пожалуйста это очень простой пример:Волатильность и безопасность потоков в Java

volatile int globalVar = 1; 

Мой поток:

if (globalVar > 0) { 
    globalVar--; 
} 

Теперь я должен решить, следует ли сделать переменную летучий достаточно для предотвращения гонки -condition и сделать эту нить безопасной.

Я знаю, что инкрементирование и декретирование не является, но я не уверен, что это другое, из-за предыдущего условия.

Я думаю, что это до сих пор не является безопасным, потому что это может быть выполнено в следующем порядке:

Thread проверяет состояние. Thread B проверяет состояние. Поток A увеличивается. Поток B увеличивается.

Я прав?

+2

Это не единственная причина; только декрементирование не является потокобезопасным. – SLaks

+1

Вам нужно думать о 'globalVar -' как загрузке потока globalVar, вычитая один из результата и записывая новое значение в globalVar, три отдельных операции. –

ответ

2

Вы верны. По этой причине он НЕ является потокобезопасным. volatile гарантирует, что два потока будут видеть обновленные значения переменной, но не защищают от нескольких строк кода.

+1

Он даже не защищает отдельные строки кода - 'globalVar -' _not_ atomic. –

+0

Которое OP highlighed: «Я знаю, что приращение и декретирование не является –

0

Чтобы сделать код безопасным, вам необходимо добавить блок вокруг проверки и изменения. не

Пример того, что может быть сделано:

volatile Integer globalVar = 1; 

Затем в методе, который выполняет работу, вы можете:

synchronized public void decrement(){ 
    if(globalVar > 0) 
      globalVar--; 
    } 
} 
+1

Это не сработает. globalVar неизменен, поэтому изменения в нем создадут новый объект, что означает, что разные потоки будут блокироваться на разных объектах. Вот почему вы должны нормально синхронизировать окончательные ссылки. –

1

Нет его не Потокобезопасная. Летучие вещества не гарантируют Атомность. Операции вроде i-- не являются атомарными, поэтому объявление i как изменчивого не помогает.

int globalVar = 1; 

lock.lock() 
try{ 
    if(globalVar > 0) 
      globalVar--; 

}finally { 
    lock.unlock(); 
} 

Приведенный выше код будет работать, вам не нужно объявлять golbalVar, как летучий здесь потому
Летучие дает две гарантии: 1. Видимость 2. переупорядочения

В то время как

Синхронизация/блокировка/разблокировка Дайте три гарантии 1.Atomicity 2. Видимость 3.Reordering

Также помните, когда объект совместно используется несколькими потоками, всегда обращайтесь к этому объекту при любой синхронизации синхронизации/изменчивости чтения/записи синхронизации.

Читайте здесь превосходную статью Глава 17 JLS. Его надо читать http://jeremymanson.blogspot.in/2008/11/what-volatile-means-in-java.html http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html

0

летучих не гарантирует для атомарности. вы можете просто добавить синхронизированный блок.

synchronized(this) 
{ 
if (globalVar > 0) { 
    globalVar--; 
} 
} 
Смежные вопросы