在Java中对volatile对象进行非易失性引用的行为 [英] The behaviour of making a non-volatile reference to a volatile object in Java

查看:97
本文介绍了在Java中对volatile对象进行非易失性引用的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Coming from C/C++, I am a little confused about volatile object behavior in Java.

据我所知,Java中的volatile有两个属性:

I understand that volatile in Java has two properties:


  1. 不会将对象带入缓存,始终将其保存在主内存中。

  2. 保证发生在之前

但是我不确定如果我对对象进行新的非易失性引用会发生什么。例如,

However I am not sure what happens if I make a new non-volatile reference to object. For example,

class Example {
   private volatile Book b = null;

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

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

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

AFAIK, volatile means the "book object" that b is referencing to should be in main memory. Compiler probably implement reference as pointer internally, so the b pointer probably sit in cache. And to my understanding, volatile is a qualifier for object, not for reference/pointer.

问题是:在use方法中,本地引用不是volatile。这个本地引用是否会将基础Book对象从主内存带入缓存,实质上使对象不是易变?

The question is: in the use method, the local reference is not volatile. Would this "local" reference bring the underlying Book object from main memory into cache, essentially making the object not "volatile"?

推荐答案

没有易失物品这样的东西,也没有永远保存在主存储器中的保证。

There is no such thing as a "volatile object" nor "always keep it in main memory" guarantees.

所有 volatile 引用类型保证的变量,是对该变量的写入与后续读取同一变量之间存在发生之前的关系。

All that volatile variables of a reference type guaranty, is that there will be a happens-before relationship between a write to that variable and a subsequent read of the same variable.

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

Since happens-before relationships are transitive, they work for your example code, i.e. for b = new Book(...) all modifications made to the Book instance are committed before the reference is written to b and hence for Book local = b; local.read(); the read() is guaranteed to see all these modification made by the other thread before writing the reference.

这并不意味着 Book 实例的内存是特殊的。例如。在引用已写入 b 之后对实例所做的修改可能会或可能不会被其他线程看到,而其他线程可能只会感知到某些线程他们或者看到它们好像是按照不同的顺序制作的。

This does not imply that the Book instance’s memory was special. E.g. modifications made to the instance after the reference has been written to b may or may not be visible to other threads and other threads may perceive only some of them or see them as if being made in a different order.

所以你获取对象的引用方式无关紧要,重要的是是否在通过 b 发布对该对象的引用之前或之后进行更改。同样,只要在通过读取 b 获取引用后执行此操作,无论您如何执行对象的读取访问权限。

So it doesn’t matter which way you get the reference to the object, all that matters is whether the changes are made before or after publishing a reference to that object through b. Likewise, it doesn’t matter how you perform the read access to the object, as long as you do it after having acquired the reference by reading b.

使用 local.read(); 您通过本地变量 local 并且在 read()中,同样的引用将通过这个进行访问,但重要的是在读取对象的状态之前,您已通过读取 b 获取了参考。

With local.read(); you are accessing the object via the local variable local and within read(), the same reference will be accessed though this, but all that matters is that you have acquired the reference by reading b before reading the object’s state.

这篇关于在Java中对volatile对象进行非易失性引用的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆