2012-05-01 4 views
2

Можно создать дубликат:
When exactly do you use the volatile keyword in Java?Когда использовать изменчивый модификатор?

Когда и почему летучие Модификатор требуется в Java?

Мне интересно видеть реальное использование изменчивого модифицированного примитива или ссылки на объект.

+0

Это примерно так же, как специфический спрашивать, когда требуется 'int' или' while' – yshavit

+0

http://stackoverflow.com/questions/3488703/when-exactly-do -you-use-the-volatile-keyword-in-java –

+2

@yshavit нет, это не так. –

ответ

4

изменчивый модификатор скажет JVM о том, чтобы быть осторожным с потоками, которые работают одновременно. По сути, volatile используется для указания того, что значение переменной будет изменено различными потоками.

Декларирование летучий переменную Java означает:

  • Значение этой переменной не будет кэшировать поток локально: все читает и пишет будет идти прямо к «основной памяти»

  • Доступ к переменная действует так, как будто она заключена в синхронизированный блок, синхронизированный по себе.

Мы говорим «действует как будто» во второй точке, потому что для программиста по крайней мере (и, вероятно, в большинстве реализаций JVM) не существует реальный объект блокировки участвует.


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

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

Реальная (или основная) копия переменной обновляется в разное время, например, когда вводится синхронизированный метод. Хотя этот подход работает отлично, он может быть неэффективным время от времени. В некоторых случаях все, что действительно имеет значение, состоит в том, что главная копия переменной всегда отражает ее текущее состояние.

Для этого просто укажите переменную как volatile, которая сообщает компилятору, что она всегда должна использовать основную копию изменчивой переменной (или, по крайней мере, всегда держать личные копии в актуальном состоянии с главной копией, и наоборот). Кроме того, доступ к главной переменной должен выполняться в точном порядке, в котором они выполняются на любой частной копии.

+0

«Доступ к переменной действует так, как будто он заключен в синхронизированный блок, синхронизированный по себе». <- Это делает его похожим на 'myVolatile ++', как будто он «синхронизирован (что-то) {myVolatile ++}», что не так. – yshavit

+0

это всего лишь подсказка программисту ... никаких блокировок не задействовано ... –

+0

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

4

(Этот ответ предполагает Java 5+ - до того, что volatile были слабые гарантии.)

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

Один случай использования в параллельных классах коллекций (например, ConcurrentHashMap или LinkedBlockingQueue), где, в сочетании с вещами, как атомарный сравнить-и-набор (CAS) операции, вы можете написать правильный поточно-код без использования synchronized ,

+0

не могли бы вы упомянуть, какой ответ вы говорите о – Edge

+0

@Edge Мой ответ. Это (мой ответ) неверно для Java 1.4 и ниже, для которого не происходит - до отношений, наложенных 'volatile'. – yshavit

1

volatile modifier сообщает compiler, что variable, измененный изменчивым, может быть неожиданно изменен другими частями вашей программы. Одна из таких ситуаций включает в себя многопоточные программы.
В многопоточной программе иногда два или более threads делятся одинаковыми instance variable. Для соображений эффективности каждый thread может хранить свою собственную частную копию такой общей переменной (in cache). Реальная (или основная) копия (in ram) variable обновляется в разное время, например, когда вводится synchronized method.
Хотя этот подход работает нормально, он может быть неэффективным в разы. В некоторых случаях все, что действительно имеет значение, состоит в том, что главная копия переменной всегда отражает ее текущее состояние. Для этого просто укажите variable as volatile, который сообщает compiler, что он должен всегда использовать основную копию volatile variable (кеш не будет поддерживаться). Кроме того, доступ к главной переменной должен выполняться в точном порядке, в котором они выполняются на любой частной копии.
EX ...

public class snippet1 implements Runnable{ 
volatile int num =0; 

public void run(){ 
    Thread t = Thread.currentThread(); 
    String name = t.getName(); 
    if(name.equals("Thread1")){ 
     num=10; 
    } 
    else{ 
     System.out.println("value of num is :"+num); 
    } 

} 
public static void main(String args[]) throws InterruptedException{ 
    Runnable r = new snippet1(); 
    Thread t1 = new Thread(r); 
    t1.setName("Thread1"); 
    t1.start(); 

    Thread.sleep(1000); 

    Thread t2 = new Thread(r); 
    t2.setName("Thread2"); 
    t2.start(); 
} 

}

в приведенном выше примере, если и не использовать летучий, то выход 2-й нити может быть 0.
, но если и поместить в энергонезависимую в его дать гарантию, что значение должно быть 10 ..

1

У вас есть хорошие ответы на первый вопрос. Второй:

Может ли один дать мне в реальное время сценария его

ИМ, вы никогда не должны когда-либо вы изменчивы. Есть более эффективные инструменты для многопоточных приложений. Это немного странно, что на этом языке высокого уровня есть это ключевое слово. Here - хорошее чтение (речь идет о C#, но Java похожа в этом вопросе).

+0

Это действительно полезный ответ! +1 –

3

Если вы работаете с многопоточным программированием, ключевое слово volatile будет более полезным. Когда несколько потоков используют одну и ту же переменную, каждый поток будет иметь свою собственную копию локального кеша для этой переменной. Итак, когда обновляется значение , оно фактически обновляется в локальном кеше не в основной переменной. Другой поток, который использует одну и ту же переменную, ничего не знает о значениях, измененных другим потоком. Чтобы избежать этой проблемы, , если вы объявите переменную как изменчивую, то она не будет сохранена в локальном кеше. Всякий раз, когда поток обновляет значения , он обновляется до основной памяти. Таким образом, другие потоки могут получить доступ к обновленному значению.

Объявление переменных летучих средств

  • Там будут никакого кэша поддерживается не означает, что все изменения, внесенные в основной памяти.
  • Доступ к этой переменной действует как синхронизированный блок, хотя он находится в синхронизированном блоке.

Пример -

public class Snippet implements Runnable{ 
volatile int num =0; 

public void run(){ 
    Thread t = Thread.currentThread(); 
    String name = t.getName(); 
    if(name.equals("Thread1")){ 
     num=10; 
    } 
    else{ 
     System.out.println("value of num is :"+num); 
    } 

} 
public static void main(String args[]) throws InterruptedException{ 
    Runnable r = new Snippet(); 
    Thread t1 = new Thread(r); 
    t1.setName("Thread1"); 
    t1.start(); 

    Thread.sleep(1000); 

    Thread t2 = new Thread(r); 
    t2.setName("Thread2"); 
    t2.start(); 
} 
} 
Смежные вопросы