2012-02-07 2 views
5

документация Oracle на атомном доступа (в http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html) говорит, что это:.Java летучие и побочные эффекты

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

У меня возникают проблемы с обволакиванием головы. Я понимаю, как работают изменчивые переменные (в> = Java 5), ​​но мне интересно, как Java решает, какой побочный эффект «подвел» к изменению изменчивой переменной.

Итак, я думаю, мой вопрос: какие побочные эффекты даны этой гарантии?

EDIT:

Так я узнал, что если нить А изменяет летучий переменную, а затем поток B читает все записи из потока А, случившиеся перед записью в энергонезависимую переменной являются «сделаны когерентным» по отношению к потоку B (т.е. кэшированные значения переменных, подлежащих вышеупомянутой записи потоком A, недействительны в потоке B). Поправьте меня если я ошибаюсь.

+0

У вас есть неправильное представление о том, как работает кеш. НО volatile write DOES FLUSH * записывает буферы *, а не кеш (кеш может быть сброшен вручную, но обычно вы этого не хотите) – bestsss

+0

Каково мое заблуждение? Похоже, что ваш ответ будет отличаться от Tom Hawtin's - может быть, вы хотите написать альтернативный ответ? –

+0

нет, это не противоречит его ответу, хотя он (его ответ) не совсем завершен. Кэш не сбрасывается (это просто разрушает любую производительность), но только модифицированные строки кэша становятся согласованными (просто). Кроме того, он не гарантирует, что спекулятивные читает прошлую запись (это очень важно). Поэтому, когда CPU возобновляет работу, все остальные могли бы/могли бы знать об этой записи (и все предыдущие записи). Вообще говоря, все процессоры делают запись доступной/видимой в точке * some *, но w/volatile write это просто * сейчас *. Я не думаю, что SO - хорошая область, чтобы объяснить, как работает когерентность кэша. – bestsss

ответ

4

Большинство многопроцессорных кешей имеют механизмы когерентности, поэтому штраф не так плох, как сброс всех кешей.

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

+0

А это имеет большой смысл. Итак, все в кеше для этого * конкретного * потока будет очищено? У Java нет способа указать, что переменная определенно не будет доступна другому потоку (и поэтому не нужно было бы краснеть)? Или, возможно, компилятор/интерпретатор выполняет какие-то оптимизации вокруг этого? –

+0

Кроме того, мне нравится ваша формулировка «после этого» - поэтому чтение из потока A в нелетучие, измененные в потоке B, может быть устаревшим до тех пор, пока поток A не прочитает изменчивый поток нити B, правильно? –

+1

@BT Я не эксперт по когерентности кеша. Необходимо, чтобы ни один другой кеш «не думает» имеет чистую копию строки кэша. Конечно, нет необходимости отменять все. Локальные переменные могут оставаться в регистрах. Есть некоторая возможность сохранить кучу выделенных объектов, но это довольно незначительно./Да. –

3

Взять Double Checked Locking в качестве примера. При создании объекта, многие вещи происходят под одеялом:

MyClass c=new MyClass(); 

Память выделяется, конструктор вызывается, и ячейка памяти присваивается переменной с. JVM разрешает изменять порядок действий. Это вызывает проблемы при распределении памяти, назначении значения и прерывании потока и использует значение перед вызовом конструктора.

volatile MyClass c=new MyClass(); 

В соответствии с правилами 1.5, гарантировано, что задание будет последним из этих событий. «Побочные эффекты» - это распределение и вызов конструктора.

+0

Это разумный пример, но он не объясняет, как java решает, какая сторона влияет на пропаганду или когда. Ответ Тома объясняет это очень кратко. –