2013-04-19 5 views
5

Этот вопрос несколько продолжение и расширение этого, как мне кажется идеальный вопрос: How does assigning to a local variable help here?Доступ к изменчивым полей через локальные переменные

Этого вопроса, основанный на Item 71 из Effective Java, где он предложил ускорить работу путем введения локальной переменной в целях доступа volatile поля:

private volatile FieldType field; 
FieldType getField() { 
    FieldType result = field; 
    if (result == null) { // First check (no locking) 
     synchronized(this) { 
     result = field; 
     if (result == null) // Second check (with locking) 
      field = result = computeFieldValue(); 
     } 
    } 
    return result; 
} 

Итак, мой вопрос более общий:

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

I.e. некоторые идиомы:

  1. мы имеем некоторое volatile поле, называют его просто volatileField;

  2. , если мы хотим, чтобы прочитать его значение в методе многопоточной, мы должны:

    1. создать локальную переменную с таким же типом: localVolatileVariable
    2. присвоить значение летучего поле: localVolatileVariable = volatileField
    3. чтения значение из этой местной копии, например:

      if (localVolatileVariable != null) { ... } 
      
+0

Как этот вопрос отличается от того, на который вы ссылаетесь? Кажется, вы хотите получить ответ на ситуацию шире, чем сценарий «инициализируйте ленивую нагрузку» для данного фрагмента кода, показанного там (и здесь). Но я не могу сказать, что ответ не может быть больше, чем «это зависит». – Thilo

+0

Это другое, что я просто хочу понять: эта оптимизация применима только к конкретному случаю, описанному в «Элементе 71», или это обычный подход для чтения «volatile» полей? – Andremoniy

ответ

3

Вы, , должны присваивать переменные переменным локальным полям, если вы планируете выполнять какую-либо многоступенчатую логику (предполагая, конечно, что поле изменчиво).

, например:

volatile String _field; 

public int getFieldLength() { 
    String tmp = _field; 
    if(tmp != null) { 
    return tmp.length(); 
    } 
    return 0; 
} 

, если вы не использовали локальную копию _field, то значение может изменяться между «если» теста и «длины()» метод вызова, потенциально может привести к NPE.

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

1

Есть две стороны монеты.

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

С другой стороны, в теории этот код разрушает JMM. Поскольку по некоторым причинам некоторым JVM разрешено переупорядочить computeFieldValue с назначением, и вы видите частично инициализированный объект. Это возможно, если переменная read не является порядком с переменной write.

field = result = computeFieldValue(); 

не произойдет до

if (result == null) { // First check (no locking) 

Пока Java-код должен быть «написать один раз запустить везде» DCL является плохой практикой и следует избегать. Этот код нарушен и не является предметом рассмотрения.

Если у вас есть несколько чтений изменчивой переменной в методе, назначив ее локальной переменной, вы сначала минимизируете такие чтения, которые стоят дороже. Но я не думаю, что вы получаете повышение производительности. Вероятно, это будет теоретическое улучшение. Такая оптимизация должна быть оставлена ​​JIT и не является предметом соображений разработчика. Я согласен с this.

+0

С одной стороны, присвоение изменчивых работ -> он не пишет на изменчивый, он читает один. – Eugene

+0

"field = result = computeFieldValue()" здесь он пишет. Это вариация классического анти-шаблона DCL. – Mikhail

+0

fyi, образец DCL, показанный в OP, не был сломан (это «исправленная» версия). не уверен в своем сообщении, подразумеваете ли вы, что это правильно или нет. – jtahlborn

0

Вместо потенциального выполнения TWO читает изменчивые переменные, он делает только один. Чтение volatile, вероятно, немного медленнее обычной переменной. Но даже если это так, мы говорим о nano секундах здесь.

+0

Ну, но Джошуа Блох говорит о 25% лучшей производительности на своей машине :) – Andremoniy

+1

@Andremoniy, который был некоторое время назад он это написал. И 25% от 1 nano секунд si все еще очень мало. Слишком мало для меня. – Eugene

Смежные вопросы