java 什么时候使用 Volatile 修饰符?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10393728/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When to use Volatile modifier?
提问by Rakesh Goswami
Possible Duplicate:
When exactly do you use the volatile keyword in Java?
When and why volatile modifier is required in java?
java中何时以及为什么需要 volatile 修饰符?
I am interested in seeing a real world usage of a volatile modified primitive or object reference.
我有兴趣看到 volatile 修改的原语或对象引用的真实世界用法。
回答by Vineet Menon
volatile modifier will tell the JVM to be cautious of the threads which runs concurrently. Essentially, volatile is used to indicate that a variable's value will be modified by different threads.
volatile 修饰符会告诉 JVM 小心并发运行的线程。本质上, volatile 用于指示变量的值将被不同的线程修改。
Declaring a volatile Java variable means:
声明一个 volatile Java 变量意味着:
The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory"
Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself.
此变量的值永远不会在线程本地缓存:所有读取和写入都将直接进入“主内存”
对变量的访问就像它被包含在一个同步块中一样,它本身是同步的。
We say "acts as though" in the second point, because to the programmer at least (and probably in most JVM implementations) there is no actual lock object involved.
我们在第二点说“好像”,因为至少对程序员(并且可能在大多数 JVM 实现中)不涉及实际的锁对象。
The volatilemodifier tells the compiler that the variable modified by volatile can be changed unexpectedly by other parts of your program. One of these situations involves multithreaded programs.
该挥发性修饰符告诉编译器被volatile修饰的变量可以通过程序的其他部分意外更改。其中一种情况涉及多线程程序。
In a multithreaded program, sometimes, two or more threads share the same instance variable. For efficiency considerations, each thread can keep its own, private copy of such a shared variable.
在多线程程序中,有时,两个或多个线程共享同一个实例变量。出于效率考虑,每个线程都可以保留自己的此类共享变量的私有副本。
The real (or master) copy of the variable is updated at various times, such as when a synchronized method is entered. While this approach works fine, it may be inefficient at times. In some cases, all that really matters is that the master copy of a variable always reflects its current state.
变量的真实(或主)副本在不同时间更新,例如在输入同步方法时。虽然这种方法工作正常,但有时可能效率低下。在某些情况下,真正重要的是变量的主副本始终反映其当前状态。
To ensure this, simply specify the variable as volatile, which tells the compiler that it must always use the master copy of a volatile variable (or, at least, always keep any private copies up to date with the master copy, and vice versa). Also, accesses to the master variable must be executed in the precise order in which they are executed on any private copy.
为了确保这一点,只需将变量指定为 volatile,它告诉编译器它必须始终使用 volatile 变量的主副本(或者,至少,始终保持任何私有副本与主副本保持同步,反之亦然) . 此外,必须按照在任何私有副本上执行的精确顺序来执行对主变量的访问。
回答by Subhrajyoti Majumder
If you are working with the multi-threaded programming, the volatile keyword will be more useful. When multiple threads using the same variable, each thread will have its own copy of the local cache for that variable. So, when it's updating the value, it is actually updated in the local cache not in the main variable memory. The other thread which is using the same variable doesn't know anything about the values changed by the another thread. To avoid this problem, if you declare a variable as volatile, then it will not be stored in the local cache. Whenever thread are updating the values, it is updated to the main memory. So, other threads can access the updated value.
如果您正在使用多线程编程,那么 volatile 关键字会更有用。当多个线程使用同一个变量时,每个线程将拥有该变量的本地缓存副本。因此,当它更新值时,它实际上是在本地缓存中而不是在主变量内存中更新。使用相同变量的另一个线程对另一个线程更改的值一无所知。为了避免这个问题,如果你将一个变量声明为 volatile,那么它就不会被存储在本地缓存中。每当线程更新值时,它都会更新到主内存。因此,其他线程可以访问更新后的值。
Declaring a variable volatile means
声明一个变量 volatile 意味着
- There will be no cache maintained means all the changes made in main memory.
- Access to this variable acts as synchronized block, even though it is in synchronized unit.
- 将没有缓存维护意味着在主内存中所做的所有更改。
- 对该变量的访问充当同步块,即使它在同步单元中。
Example -
例子 -
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();
}
}
回答by yshavit
(This answer assumes Java 5+ -- before that, volatile
had weaker guarantees.)
(这个答案假设 Java 5+ - 在此之前,volatile
有较弱的保证。)
It's useful when you want to ensure a memory barrier, aka a formal "happens-before" relationship, between a write to a field and a subsequent read to that field by a separate thread. Synchronization can also give you that relationship, as well as other multithreading guarantees, but it's a tad slower and can create synchronization bottlenecks.
当您想确保在写入字段和随后由单独线程读取该字段之间存在内存屏障时,它很有用,也就是正式的“发生在之前”关系。同步也可以为您提供这种关系,以及其他多线程保证,但它有点慢并且会造成同步瓶颈。
One use case is in concurrent collection classes (like ConcurrentHashMap
, or LinkedBlockingQueue
) where, in conjunction with things like atomic compare-and-set (CAS) operations, you can write correct thread-safe code without having to use synchronized
.
一个用例是在并发集合类(如ConcurrentHashMap
、 或LinkedBlockingQueue
)中,结合诸如原子比较和设置(CAS)操作之类的东西,您可以编写正确的线程安全代码而无需使用synchronized
.
回答by Sumit Singh
The volatile modifier
tells the compiler
that the variable
modified by volatile can be changed unexpectedly by other parts of your program. One of these situations involves multithreaded programs.
In a multithreaded program, sometimes, two or more threads
share the same instance variable
. For efficiency considerations, each thread
can keep its own, private copy of such a shared variable (in cache
). The real (or master) copy (in ram
) of the variable
is updated at various times, such as when a synchronized method
is entered.
While this approach works fine, it may be inefficient at times. In some cases, all that really matters is that the master copy of a variable always reflects its current state. To ensure this, simply specify the variable as volatile
, which tells the compiler
that it must always use the master copy of a volatile variable
(no cache will be maintain ). Also, accesses to the master variable must be executed in the precise order in which they are executed on any private copy.
EX...
该volatile modifier
通知compiler
将variable
被volatile修饰可以通过程序的其他部分意外更改。其中一种情况涉及多线程程序。
在多线程程序中,有时,两个或更多threads
共享相同的instance variable
. 出于效率考虑,每个人都thread
可以保留自己的此类共享变量 ( in cache
) 的私有副本。的真实(或主)副本 ( in ram
)variable
在不同时间更新,例如在synchronized method
输入a 时。
虽然这种方法工作正常,但有时可能效率低下。在某些情况下,真正重要的是变量的主副本始终反映其当前状态。为了确保这一点,只需指定variable as volatile
,它告诉compiler
它必须始终使用 a 的主副本volatile variable
(不会维护缓存)。此外,必须按照在任何私有副本上执行的精确顺序来执行对主变量的访问。
前任...
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();
}
}
}
in above example if u don't use volatile then the output of 2nd thread may be 0.
but if u put as volatile the it give u guaranty that the value should be 10..
在上面的例子中,如果你不使用 volatile 那么第二个线程的输出可能是 0
。
回答by Lukasz Madon
You got good answers for the first question. The second one:
你对第一个问题有很好的回答。第二个:
Can any one give me real time scenario of it
谁能给我实时场景
IMO, you should never ever you volatile. There are better tools for multithreaded apps. It's a bit bizarre that such a high level language has this keyword. Hereis a good read (It's about C#, but Java is similar in this matter).
IMO,您永远不应该变得不稳定。多线程应用程序有更好的工具。这么高级的语言有这个关键字,有点奇怪。这是一个很好的读物(它是关于 C#,但 Java 在这方面是相似的)。