2013-11-30 2 views
3

Я иду через книгу потоков Java. Я наткнулся на это заявлениеНекоторые сомнения относительно летучих и атомных классов?

Заявление 1: - «летучие переменные могут безопасно использоваться только для одной нагрузки или работы магазина и не может быть применен к длинных или двойных variales Эти ограничения делают использование летучих переменных. необычный "

Я не понял, что здесь означает одна загрузка или операция хранения? почему volatile не может быть применяется к длинным или двойным variales?

Заявление 2: - «летучий целое число, не может быть использован с оператором ++ ++, потому что оператор содержит множественного класса instructions.The AtomicInteger имеет метод, который позволяет целое число, что имеет место быть увеличивается атомарно. "

Почему Volatile integer не может использоваться с оператором ++ и как AtomicInteger обращается к нему?

ответ

5

Заявление 1: - «летучие переменные может безопасно использоваться только для одной нагрузки или работы магазина и не может быть применены к длинному или двойному variales Этих ограничения делают использование летучих переменными незаурядным.»

Что ?! Я считаю, что это просто неправильно. Возможно, ваша книга устарела.

Заявление 2: - «летучий целое число не может быть использован с оператором ++ ++, потому что оператор содержит множественный класс instructions.The AtomicInteger имеет метод, который позволяет целое число, что имеет место быть увеличено атомарно.»

Точно, что он говорит. Оператор ++ на самом деле переводится в машинный код, как это (в Java-подобный псевдокод):

sync_CPU_caches(); 
int processorRegister = variable; 
processorRegister = processorRegister + 1; 
variable = processorRegister; 
sync_CPU_caches(); 

Это не поточно-, потому что даже если он имеет барьер памяти, и читает атомарно и пишет атомарно, не гарантируется, что вы не получите переключатель потоков в середине, а регистры процессора являются локальными для ядра процессора (подумайте о них как «локальные переменные» внутри ядра процессора). Но AtomicInteger является потокобезопасным - он, вероятно, реализован с использованием специальных инструкций машинного кода, таких как сравнение и обмен.

+1

Его книга действительно устарела. [JLS §17.7] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.7): 'Запись и чтение изменчивых длинных и двойных значений всегда являются атомарными . Я подозреваю, что книга, возможно, была написана до Java 5, когда контракт с 'volatile' был [все wonky] (http://stackoverflow.com/a/10451364/758280). – Jeffrey

+0

@Robin. Благодарю. Мой вопрос в том, как оператор ++ не является потокобезопасным, тогда как Atomic integer является потокобезопасным. Можете ли вы рассказать об этом на простом примере? –

0

Основная цель изменчивых переменных заключается не в том, чтобы обеспечить немедленный потокобезопасный доступ к этой переменной, но для обеспечения безопасности так называемого -безопасности до.

Теоретически вызов

volatile int i = 0; 

и

int i = 0; 

не имеет никакого значения, так как 32-битное слово пишется атомарно в любом случае (на 32 битных и выше машин, чтобы быть правильным). Так как указатели 32/64-битные int также внутри, в основном есть только одна операция, которую volatile делает атомарно, и это если вы используете 64-битную длину в 32-битной среде.

происходит до, однако это то, что на самом деле испортило вышеприведенный пример. Чтобы понять это, вам нужно знать, что потоки не используют фактическую память переменной, о которой идет речь, но могут сделать ее копии для ускорения выполнения и могут переопределить операторы для оптимизации. Теперь, если у вас есть что-то вроде:

Thread A: value = 1; doIt = true; 
Thread B: if (doIt) { doDoIt(value); } 

Вполне возможно, что в Thread B doIt верно, но value еще не один, потому что порядок исполнения может быть изменен JVM, или новый value имеет просто еще не был передан в копию Thread B's value.

Если doIt объявлен летучий вместо этого, то в момент доступа к нему, то JVM гарантирует, что весь код до того, что доступ уже выполнен и транслировались. Таким образом, приведенный выше пример является фактической причиной использования изменчивости.