今天工作时,我在Java中遇到了volatile关键字。不是很熟悉,我找到了这个解释。
鉴于那篇文章详细解释了所讨论的关键字,您曾经使用过它吗?或者您曾经看到过以正确方式使用该关键字的情况吗?
今天工作时,我在Java中遇到了volatile关键字。不是很熟悉,我找到了这个解释。
鉴于那篇文章详细解释了所讨论的关键字,您曾经使用过它吗?或者您曾经看到过以正确方式使用该关键字的情况吗?
当前回答
用volatile关键字声明的变量有两个主要特性,这使得它很特殊。
如果我们有一个易失性变量,它不能被任何线程缓存到计算机的(微处理器)缓存内存中。访问总是发生在主存中。 如果对一个易失性变量正在进行写操作,并且突然请求了一个读操作,那么可以保证写操作将在读操作之前完成。
以上两个品质推断了这一点
所有读取volatile变量的线程肯定会读取最新的值。因为没有缓存值可以污染它。而且读请求只有在当前写操作完成后才会被授予。
另一方面,
如果我们进一步研究我提到的#2,我们可以看到volatile关键字是维护一个共享变量的理想方法,它有n个读线程,只有一个写线程可以访问它。一旦我们添加了volatile关键字,就完成了。没有任何线程安全方面的开销。
交谈,
我们不能仅仅使用volatile关键字来满足有多个写入线程访问它的共享变量。
其他回答
下面是一个非常简单的代码,演示了volatile for variable的需求,它用于从其他线程控制线程执行(这是需要volatile的一个场景)。
// Code to prove importance of 'volatile' when state of one thread is being mutated from another thread.
// Try running this class with and without 'volatile' for 'state' property of Task class.
public class VolatileTest {
public static void main(String[] a) throws Exception {
Task task = new Task();
new Thread(task).start();
Thread.sleep(500);
long stoppedOn = System.nanoTime();
task.stop(); // -----> do this to stop the thread
System.out.println("Stopping on: " + stoppedOn);
}
}
class Task implements Runnable {
// Try running with and without 'volatile' here
private volatile boolean state = true;
private int i = 0;
public void stop() {
state = false;
}
@Override
public void run() {
while(state) {
i++;
}
System.out.println(i + "> Stopped on: " + System.nanoTime());
}
}
当不使用volatile时:即使在“stop on: xxx”之后,你也永远不会看到“Stopped on: xxx”消息,并且程序继续运行。
Stopping on: 1895303906650500
当使用volatile时:你会立即看到'Stopped on: xxx'。
Stopping on: 1895285647980000
324565439> Stopped on: 1895285648087300
演示:https://repl.it/repls/SilverAgonizingObjectcode
是的,我经常使用它——它对多线程代码非常有用。你指的那篇文章很好。不过有两件重要的事情要记住:
You should only use volatile if you completely understand what it does and how it differs to synchronized. In many situations volatile appears, on the surface, to be a simpler more performant alternative to synchronized, when often a better understanding of volatile would make clear that synchronized is the only option that would work. volatile doesn't actually work in a lot of older JVMs, although synchronized does. I remember seeing a document that referenced the various levels of support in different JVMs but unfortunately I can't find it now. Definitely look into it if you're using Java pre 1.5 or if you don't have control over the JVMs that your program will be running on.
是的,当你想要一个可变变量被多个线程访问时,必须使用volatile。这不是很常见的用例,因为通常你需要执行不止一个原子操作(例如,在修改变量之前检查变量状态),在这种情况下,你会使用同步块代替。
每个访问volatile字段的线程在继续之前都会读取它的当前值,而不是(可能)使用缓存的值。
只有成员变量可以是易变的或瞬变的。
绝对是的。(不仅是Java, c#也是如此。)有时,您需要获取或设置一个值,该值保证是给定平台上的原子操作,例如int或boolean,但不需要线程锁定的开销。volatile关键字允许您确保在读取值时获得的是当前值,而不是在另一个线程上写入时被废弃的缓存值。