简体   繁体   English

引擎盖下的java中的易失性关键字

[英]Volatile keyword in java under the hood

I have had a little argument with my teacher about the volatile keyword in java. 我和老师讨论过java中的volatile关键字。 Is it right to say that when a variable is declared as a volatile : 说变量被声明为volatile时是否正确:

The value of this variable will never be cached thread-locally: all reads and writes will go straight to the "main memory". 该变量的值永远不会被线程本地缓存:所有读取和写入将直接进入“主存储器”。

My teachers opinion is that: 我老师的意见是:

volatile keyword does not promise the value of the variable will be saved in the main memory. volatile关键字保证变量的值将保存在主内存中。

Can someone resolve our conflict? 有人能解决我们的冲突吗? Thank you! 谢谢!

For the exact meaning of keywords such as volatile , look at the Java Language Specification to see the official meaning. 有关volatile等关键字的确切含义,请查看Java语言规范以查看官方含义。

JLS paragraph 8.3.1.4 explains what volatile means: JLS第8.3.1.4段解释了volatile含义:

A field may be declared volatile, in which case the Java Memory Model ensures that all threads see a consistent value for the variable (§17.4). 字段可以声明为volatile,在这种情况下,Java Memory Model可以确保所有线程都看到变量的一致值(第17.4节)。

Paragraph 17.4 explains the Java Memory Model. 第17.4节解释了Java内存模型。 The memory model gives you certain guarantees about what happens to data after each statement in a program. 内存模型为您提供有关程序中每个语句之后数据发生情况的某些保证。

If you study that carefully, you'll find that volatile means that if you write to a volatile variable, you have the guarantee that other threads will see what was written. 如果仔细研究,你会发现volatile意味着如果你写一个volatile变量,你可以保证其他线程会看到写的内容。 How this is implemented in practice is deliberately not specified. 故意没有具体说明如何在实践中实施。 It may be implemented by forcing a write to main memory, but JVM implementers are free to choose a different, possibly more efficient mechanism. 它可以通过强制写入主内存来实现,但JVM实现者可以自由选择不同的,可能更有效的机制。

So, strictly speaking, your teacher is right. 所以,严格来说,你的老师是对的。 It does not necessarily mean that the value is written to main memory; 它并不一定意味着将值写入主存储器; although in practice this might well be the case - but it depends on the particular JVM implementation. 虽然在实践中可能就是这种情况 - 但这取决于特定的JVM实现。

What volatile does is to ignore all local CPU caches; volatile作用是忽略所有本地CPU缓存; or equivalently, refresh the cache line containing that volatile variable to be refreshed from main memory. 或者等效地刷新包含要从主存储器刷新的volatile变量的高速缓存行。 Thus as the documentation suggests, it makes sure all reads directly read up from main memory and all writes go directly to the main memory. 因此,正如文档所示,它确保所有读取都直接从主存储器读取,并且所有写入都直接进入主存储器。

In addition to this, volatile also have the atomic operation guarantee. 除此之外, volatile还具有原子操作保证。 It makes sure the variable prefixed by this keyword would be read or written in full as if it's a single instruction. 它确保以此关键字为前缀的变量将被完整地读取或写入,就像它是单个指令一样。 (as in the contrast, you won't worry a 64-bit long integer written by 2 threads end up with the first 32-bit from one thread and the 2nd 32-bit from another thread.) Thus in some certain situation eg if you use volatile on a 64 bit long integer on a 32 bit machine, the JVM might need to do more than just a "volatile" instruction. (相比之下,你不会担心由2个线程写入的64位长整数最后是来自一个线程的第一个32位和来自另一个线程的第二个32位。)因此在某些情况下例如如果在32位机器上使用64位长整数的volatile时,JVM可能需要做的不仅仅是“易失性”指令。 Some more documentations are at https://blogs.oracle.com/dave/entry/java_memory_model_concerns_on . 更多文档位于https://blogs.oracle.com/dave/entry/java_memory_model_concerns_on

To your specific question. 针对您的具体问题。

  • On reading a volatile in Java, it makes sure the value of the variable is from main memory. 在读取Java中的volatile时,它确保变量的值来自主内存。
  • On writing a volatile in Java, it makes sure the value of the variable is written to the main memory. 在Java中编写volatile时,它确保将变量的值写入主内存。

Having said the above - this is from a "logical" point of view. 说了上面的话 - 这是从“逻辑”的角度来看的。 In the reality, modern CPUs employ complex caching policy and it can sometimes guarantee the above is true without actually writing to the main memory. 实际上,现代CPU采用复杂的缓存策略,有时可以保证上述情况不会实际写入主内存。 However it only does so on realizing the same effect can absolutely be achieved as a performance optimization step. 然而,它只能实现相同的效果才能绝对实现作为性能优化步骤。 But I think this is beyond the scope of the discussion. 但我认为这超出了讨论的范围。

I'll just quote two paragraphs from docs 我将引用文档中的两段

first 第一

A field may be declared volatile, in which case the Java Memory Model ensures that all threads see a consistent value for the variable (§17.4). 字段可以声明为volatile,在这种情况下,Java Memory Model可以确保所有线程都看到变量的一致值(第17.4节)。

second 第二

The memory model describes possible behaviors of a program. 内存模型描述了程序的可能行为。 An implementation is free to produce any code it likes, as long as all resulting executions of a program produce a result that can be predicted by the memory model. 只要程序的所有结果执行产生可由内存模型预测的结果,实现就可以自由地生成它喜欢的任何代码。

This provides a great deal of freedom for the implementor to perform a myriad of code transformations, including the reordering of actions and removal of unnecessary synchronization. 这为实现者提供了大量的自由来执行无数的代码转换,包括重新排序动作和删除不必要的同步。


Now If you will refer to most of the tutorials regarding votatile keyword in java , most of them will suggest the same thing as you suggested, ie, The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory" . 现在,如果您将参考大多数关于votatile keyword in java的教程, votatile keyword in java大多数教程都会提出与您建议的相同的东西,即, 此变量的值永远不会被线程本地缓存:所有读取和写入都将直接进行到“主要记忆”

But docs make no guarantee about it. 但是文档并不能保证它。 Although it never denies it as well. 虽然它永远不会否认它。 It just says this is the possbile behaviour . 它只是说这是可能的行为

So I would say that your teacher is correct. 所以我会说你的老师是对的。 According to docs (and not the most tutorials other than docs), Volatile keyword definitely does not promise that the value of the variable will be saved in the main memory. 根据文档(而不是比其他文档的最教程)volatile关键字绝对答应,该变量的值将被保存在主存储器。

However, this doesn't makes you wrong, it all depends upon the JVM implementation. 但是,这不会让你错,这一切都取决于JVM的实现。

Here it goes: https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.3.1.4 From Java 8 SE specification: 在这里: https//docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.3.1.4从Java 8 SE规范:

A field may be declared volatile, in which case the Java Memory Model ensures that all threads see a consistent value for the variable 字段可以声明为volatile,在这种情况下,Java Memory Model可确保所有线程都看到变量的一致值

It's described very nice IMHO in "Java Concurrency in Practice". 它在“Java Concurrency in Practice”中描述了非常好的IMHO。 https://jcip.net/ Perhaps you have it in your library? https://jcip.net/也许你的图书馆里有它?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM