当前位置: 首页 > 知识库问答 >
问题:

Java中对易失性对象进行非易失性引用的行为

禹昊穹
2023-03-14

来自C/C++,我对Java中的volatile对象行为有点困惑。

    null
class Example {
   private volatile Book b = null;

   public init() { b = new Book(...); }

   public use() {
     Book local = b;
     local.read();
   }
}

faik,volatile意味着b引用的“book对象”应该在主内存中。编译器可能在内部实现引用作为指针,因此b指针可能位于缓存中。我的理解是,volatile是对象的限定符,而不是引用/指针的限定符。

问题是:在使用方法中,本地引用不是易失性的。这个“本地”引用会不会把底层的Book对象从主存带到缓存中,实质上使对象不“易失”?

共有1个答案

宋明亮
2023-03-14

没有所谓的“易失性对象”,也没有“始终将其保留在主存中”的保证。

引用类型的volatile变量的所有保证是,在对该变量的写入和对同一变量的后续读取之间将存在一种happens-before关系。

由于happens-before关系是可传递的,因此它们适用于示例代码,即对于b=new Book(...),在将引用写入b之前提交对Book实例的所有修改,因此对于Book local=b;local.read();read()保证在写入引用之前看到其他线程所做的所有这些修改

因此获取对象引用的方式并不重要,重要的是更改是在通过b发布对该对象的引用之前还是之后进行的。同样,如何执行对对象的读取访问并不重要,只要您在通过读取b获得引用之后执行。

使用local.read();时,您通过局部变量local访问对象,并且在read()中,将通过this访问相同的引用,但重要的是您在读取对象的状态之前通过读取b获得了引用。

 类似资料:
  • C11 6.7.3类型限定符,第7段规定: 这里,指针的类型为,但我关心的是当实际指向的对象是非易失性的时会发生什么,特别是编译器是否可以将从对的单个访问转换为以下形式的两个访问: 这显然会使代码不正确。因此,目标是确定是否所有这样的指向对象实际上都需要。

  • 来自ISO/IEC 9899:201x第5.1.2.3节程序执行第4段: 关于volatile对象,这里允许的优化是什么?有人能给出一个可以优化掉的易失性访问的例子吗? 由于Volatile访问是一种可观察的行为(在第6段中描述),似乎没有任何优化可以针对Volatile进行,所以,我很想知道第4节中允许的优化是什么。

  • 在阅读了这个问题和这个(尤其是第二个答案)之后,我对volatile及其关于记忆障碍的语义感到非常困惑。 在上面的例子中,我们写入一个易失性变量,这会导致一个mitch,这反过来会将所有挂起的存储缓冲区/加载缓冲区刷新到主缓存,使其他缓存行无效。 然而,非易失性字段可以优化并存储在寄存器中,例如?那么,我们如何才能确保给定一个写入易失性变量之前的所有状态变化都是可见的呢?如果我们有1000件东西呢

  • 我对下面的代码段有一个问题。结果可能有一个结果[0,1,0](这是用JCStress执行的测试)。那么这是怎么发生的呢?我认为数据写入(data=1)应该在Actor2(guard2=1)中写入到guard2之前执行。我说得对吗?我问,因为很多时候我读到挥发物周围的说明没有重新排序。此外,根据这一点:http://tutorials.jenkov.com/java-concurrency/vola

  • 我正在使用以下字段: 哪里 这样发布日期图安全吗?我的意思是,易失性字段意味着对一个字段的引用不会缓存在CPU寄存器中,并且在任何时候访问它都可以从内存中读取。 因此,我们不妨为映射的

  • 如果是,如果被添加到数组中,强制转换会受到什么影响?谢谢你! 编辑:@cacahuete Frito链接了一个非常相似的问题:带有'volatile'数组的'memcpy((void*)dest,src,n)'安全吗?