简体   繁体   English

Java volatile关键字

[英]Java volatile keyword

I know that there is a lot of questions about volatile but I just got confused from this discussion: Java: how volatile guarantee visibility of "data" in this piece of code? 我知道有很多关于volatile的问题,但是我对此讨论感到困惑: Java:volatile如何保证这段代码中“数据”的可见性?

Every web site that I read says that a variable could be stored in cached ( making this value invisible for another threads ) I even found this example https://dzone.com/articles/java-volatile-keyword-0 我阅读的每个网站都说可以将变量存储在缓存中(使该值对其他线程不可见),我什至发现了这个示例https://dzone.com/articles/java-volatile-keyword-0

So my first question would be: Does Java stores variable values in cache memory ( in which one ? l1 l2 or l3 ) 所以我的第一个问题是:Java是否将变量值存储在高速缓存中(在其中吗?l1 l2或l3)

My other question is the visibility part. 我的另一个问题是可见性部分。 For example: 例如:

public int num1 = 1;
public int num2 = 2;
public int num3 = 3;
public int num4 = 4;
public int num5 = 5;
...
num1 = 10;
num2 = 20;
num3 = 30;
num4 = 40;
num5 = 50;

In this example the execution order of variables is not guaranteed. 在此示例中,不能保证变量的执行顺序。 If I make num2 volatile it assures me that the order execution of num1, num2 and num3 will be exactly like its defined, but its not assuring me for num4 and num5 ? 如果我使num2易失,则可以确保num1,num2和num3的顺序执行与定义的顺序完全相同,但不能保证num4和num5的执行能力吗?

EDIT I just finished reading the article of Peter Lawrey http://vanillajava.blogspot.com.es/2012/01/demonstrating-when-volatile-is-required.html and he wrote "Without volatile, this breaks down in a number of possible ways. One way is that the two threads each think they have changed the value and are waiting for the other ie each has its own cached copy of the value. " 编辑我刚读完彼得·劳瑞(Peter Lawrey)的文章,网址为http://vanillajava.blogspot.com.es/2012/01/demonstrating-when-volatile-is-required.html ,他写道:“没有波动,这会分解为许多一种方式是,两个线程各自认为自己已经更改了值,并且正在等待对方,即每个线程都有自己的值的缓存副本。

Sooo I'm even more confused .. about that 太让我困惑了..

Sorry for the probably dumb question but I really confused about that. 很抱歉,这个问题可能很愚蠢,但我对此感到非常困惑。

Most programs, including the JVM do not explicitly place variables in any particular cache. 包括JVM在内的大多数程序都不会在任何特定的缓存中明确放置变量。 The only decision the JIT makes is JIT做出的唯一决定是

  • does it eliminate the variable entirely? 它会完全消除变量吗?
  • does it place it in a register and which one? 是否将其放置在寄存器中,哪一个?
  • does it place it on the stack in memory? 是否将其放在内存中的堆栈上? (And where relative to the top of the stack) (以及相对于堆栈顶部的位置)
  • does it place it in an object on the heap? 是否将其放置在堆中的对象中? (And where in the object) (以及对象中的何处)

The only choice you have is whether the variable is in an object or on the stack. 您唯一的选择是变量是在对象中还是在堆栈中。 (You also have the choice to avoid using a variable at all) note, if you place the field in an object the jit can still put it only the stack if it can avoid creating the object. (您也可以选择完全避免使用变量)注意,如果将字段放置在对象中,如果jit可以避免创建对象,它仍然只能将其放在堆栈中。

The only visibility guarantee that making num2 volatile provides is that if you see num2 == 20 you must see num1 == 10. You are also guaranteed you will see num2 == 20 at some point in other threads. 使num2变得可变的唯一可见性保证是,如果看到num2 == 20,则必须看到num1 ==10。您还可以保证在其他线程的某个点上看到num2 == 20。 You may see num3 == 3 or num3 == 30. It's possible you might never see num3 in another thread as it's not volatile or final. 您可能会看到num3 == 3或num3 ==30。可能您可能再也不会在另一个线程中看到num3了,因为它不是volatile或final。 You might see num3 == 0 which is the uninitialised value if you read that field in another thread before num2 is written a second time. 如果您在第二次写入num2之前在另一个线程中读取了该字段,则可能会看到num3 == 0,这是未初始化的值。

each has its own cached copy of the value. 每个都有自己的值的缓存副本。

This is not determined by Java but is an implementation detail of CPUs. 这不是由Java确定的,而是CPU的实现细节。 Each core has it's own L1 and L2 caches in x64, Sparc and ARM. 每个内核在x64,Sparc和ARM中都有自己的L1和L2缓存。 These caches are local to each core for speed which means they might not be in sync with each other. 这些高速缓存对于每个核心而言都是本地的,这意味着它们可能彼此不同步。 Ensuring they are always in sync would slow them down dramatically. 确保它们始终保持同步将大大降低它们的速度。

When you look for an exact description of such behaviour, it's always good to have a look into the Java Language Specification . 当您寻找此类行为的准确描述时,最好阅读一下Java Language Specification In the linked chapter, you'll find information about threading behaviour and compiler reordering and how volatile comes into play here. 在链接的章节中,您将在此处找到有关线程行为和编译器重新排序以及volatile如何发挥作用的信息。

The order of the assignments is not affected by volatile . 分配的顺序不受volatile影响。 The keyword volatile guarantees that multiple threads accessing eg an int-value 'see' the same value. 关键字volatile保证多个线程访问例如int值“看到”相同的值。 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. 对变量的访问就好像它被封装在一个同步块中一样,它本身是同步的。

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

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