пятница, 4 января 2013 г.

volatile

Locking гарантирует и видимость и атомарность, volalite -- только видимость.

Взято из: http://www.askdev.ru/java/1512/volatile/ :

Данный модификатор актуален в многопоточных приложениях, гарантирует что
- Операции записи и чтения (выполняемые потоками) происходят напрямую с основной памятью. (в связи с вопросами эффективности каждый поток может использовать свою "локальную память").
- Операции записи, чтения значений длиной 64 бит происходят атомарно (данная операция может быть представлена как две 32-х битовые операции, что может вылиться в неприятности для не volatile переменных)
- с Java 1.5. При обращении к volatile переменной происходит синхронизация для всех локальных переменных потока с основной памятью
- с Java 1.5. Операции, стоящие в коде перед операцией записи в переменную volatile, должны быть выполнены раньше, то есть оптимизатор JVM не имеет права переставить их местами. Проблема напрямую связана с double-checking idiom, подробней можно посмотреть здесь
http://jeremymanson.blogspot.com/2008/05/double-checked-locking.html
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

Безопасно использовать:
- Записываемое значение не зависит от текущего
- Не учавствует в инвариантах с другими переменными

 Brian Goetz достаточно ясно сформулировал несколько паттернов безопасного использования volatile в своей статье
http://www.ibm.com/developerworks/java/library/j-jtp06197.html

http://en.wikipedia.org/wiki/Volatile_variable

Неожиданный подводный камень. 
JMV обеспечивает потокобезопасноть только для атомарных операций - чтение и запись переменной.
Так что инкрмент это потоконебезопасная операция
myVolatileVar++;
Чтобы сделать это потокобезопасным нужно:
int temp = 0;
synchronize( myVolatileVar ) {
  temp = myVolatileVar;
} 
temp++; 
synchronize( myVolatileVar ) {
  myVolatileVar = temp;
}
Подобный код можно не писать, а пользоваться атомиками из пакета java.util.concurrent.atomic



Комментариев нет:

Отправить комментарий