今天工作时,我在Java中遇到了volatile关键字。不是很熟悉,我找到了这个解释。
鉴于那篇文章详细解释了所讨论的关键字,您曾经使用过它吗?或者您曾经看到过以正确方式使用该关键字的情况吗?
今天工作时,我在Java中遇到了volatile关键字。不是很熟悉,我找到了这个解释。
鉴于那篇文章详细解释了所讨论的关键字,您曾经使用过它吗?或者您曾经看到过以正确方式使用该关键字的情况吗?
当前回答
如果您正在开发多线程应用程序,您将需要使用'volatile'关键字或'synchronized'以及您可能拥有的任何其他并发控制工具和技术。桌面应用就是这样一个例子。
If you are developing an application that would be deployed to application server (Tomcat, JBoss AS, Glassfish, etc) you don't have to handle concurrency control yourself as it already addressed by the application server. In fact, if I remembered correctly the Java EE standard prohibit any concurrency control in servlets and EJBs, since it is part of the 'infrastructure' layer which you supposed to be freed from handling it. You only do concurrency control in such app if you're implementing singleton objects. This even already addressed if you knit your components using frameworkd like Spring.
因此,在Java开发的大多数情况下,应用程序是一个web应用程序,并使用IoC框架,如Spring或EJB,你不需要使用'volatile'。
其他回答
Volatile变量基本上用于主共享缓存线上的即时更新(刷新),以便立即将更改反映到所有工作线程。
从oracle文档页,需要volatile变量来修复内存一致性问题:
使用易失性变量可以降低内存一致性错误的风险,因为对易失性变量的任何写入都会与该变量的后续读取建立happens-before关系。
这意味着对volatile变量的更改总是对其他线程可见。这也意味着当线程读取一个volatile变量时,它不仅看到了volatile的最新更改,还看到了导致更改的代码的副作用。
正如在Peter Parker的回答中解释的那样,在没有volatile修饰符的情况下,每个线程的堆栈都可能有自己的变量副本。通过将变量设置为volatile,可以修复内存一致性问题。
为了更好地理解,请查看jenkov教程页面。
看一下相关的SE问题,了解更多关于volatile的细节和使用volatile的用例:
Java中volatile和synchronized的区别
一个实际的用例:
你有很多线程,它们需要以特定的格式打印当前时间,例如:java.text.SimpleDateFormat("HH-mm-ss")。可以有一个类,它将当前时间转换为SimpleDateFormat,并每一秒更新一次变量。所有其他线程都可以使用这个易失性变量在日志文件中打印当前时间。
如果您正在开发多线程应用程序,您将需要使用'volatile'关键字或'synchronized'以及您可能拥有的任何其他并发控制工具和技术。桌面应用就是这样一个例子。
If you are developing an application that would be deployed to application server (Tomcat, JBoss AS, Glassfish, etc) you don't have to handle concurrency control yourself as it already addressed by the application server. In fact, if I remembered correctly the Java EE standard prohibit any concurrency control in servlets and EJBs, since it is part of the 'infrastructure' layer which you supposed to be freed from handling it. You only do concurrency control in such app if you're implementing singleton objects. This even already addressed if you knit your components using frameworkd like Spring.
因此,在Java开发的大多数情况下,应用程序是一个web应用程序,并使用IoC框架,如Spring或EJB,你不需要使用'volatile'。
The volatile key when used with a variable, will make sure that threads reading this variable will see the same value . Now if you have multiple threads reading and writing to a variable, making the variable volatile will not be enough and data will be corrupted . Image threads have read the same value but each one has done some chages (say incremented a counter) , when writing back to the memory, data integrity is violated . That is why it is necessary to make the varible synchronized (diffrent ways are possible)
如果修改是由一个线程完成的,而其他线程只需要读取这个值,则volatile将是合适的。
volatile关键字有两种不同的用法。
阻止JVM从寄存器(假设为缓存)读取值,并强制从内存读取其值。 降低内存不一致错误的风险。
阻止JVM读取寄存器中的值,并强制其读取 从内存中读取的值。
busy标志用于防止线程在设备繁忙且该标志不受锁保护的情况下继续运行:
while (busy) {
/* do something else */
}
当另一个线程关闭busy标志时,测试线程将继续执行:
busy = 0;
但是,由于busy在测试线程中经常被访问,JVM可以通过将busy的值放在寄存器中来优化测试,然后在每次测试之前测试寄存器的内容,而不读取内存中的busy值。测试线程永远不会看到busy的变化,而另一个线程只会改变内存中的busy值,从而导致死锁。将busy标志声明为volatile将强制在每次测试之前读取它的值。
降低内存一致性错误的风险。
使用易失性变量可以降低内存一致性错误的风险,因为对易失性变量的任何写入都会建立一个 “happens-before”关系与该变量的后续读取之间的关系。这意味着对volatile变量的更改总是对其他线程可见。
这种读写而不产生记忆一致性错误的技术被称为原子动作。
原子作用是指有效地同时发生的作用。原子的动作不可能中途停止:它要么完全发生,要么根本不发生。在操作完成之前,原子操作的副作用是不可见的。
下面是你可以指定的原子操作:
对于引用变量和大多数变量来说,读和写都是原子的 基本变量(所有类型,除了long和double)。 对于所有声明为volatile的变量,读和写都是原子的 (包括长变量和双变量)。
干杯!