Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java volatile参考与AtomicReference_Java_Concurrency - Fatal编程技术网

Java volatile参考与AtomicReference

Java volatile参考与AtomicReference,java,concurrency,Java,Concurrency,如果我只使用get()和set(),那么volatile对象引用和AtomicReference中的get()和set()方法之间有什么区别吗?简短的回答是:没有 从软件包文档中。引述: 原子访问和更新的记忆效应通常遵循挥发物的规则: get具有读取volatile变量的记忆效果 set具有写入(分配)一个volatile变量的记忆效果 顺便说一句,文档非常好,所有内容都解释过了 是一个较新的(Java 6+)操作,其语义无法通过volatile变量实现。有关更多信息,请参阅。不,没有 A

如果我只使用
get()
set()
,那么
volatile
对象引用和
AtomicReference
中的
get()和
set()
方法之间有什么区别吗?

简短的回答是:没有

从软件包文档中。引述:

原子访问和更新的记忆效应通常遵循挥发物的规则:

  • get
    具有读取
    volatile
    变量的记忆效果
  • set
    具有写入(分配)一个
    volatile
    变量的记忆效果
顺便说一句,文档非常好,所有内容都解释过了


是一个较新的(Java 6+)操作,其语义无法通过
volatile
变量实现。有关更多信息,请参阅。

不,没有

AtomicReference提供的额外功能是compareAndSet()方法和friends。如果您不需要这些方法,volatile引用将提供与AtomicReference.set()和.get()相同的语义。

提供普通volatile变量不提供的附加功能。正如您已经阅读了API Javadoc一样,您将知道这一点,但它也提供了一个锁,它对某些操作非常有用

但是,除非您需要此附加功能,否则我建议您使用普通的
volatile
字段。

是解决此类困惑的最佳方法之一。如果查看AtomicReference中的代码,它使用volatie变量来存储对象

private volatile V value;

所以,很明显,如果您要在AtomicReference上使用get()和set(),这就像使用易失性变量一样。但正如其他读者所评论的,AtomicReference提供了额外的CAS语义。因此,首先确定是否需要CAS语义,如果只需要,则使用AtomicReference。

有几个区别和权衡:

  • 使用
    AtomicReference
    get/set具有与volatile字段相同的JMM语义(如javadoc所述),但是
    AtomicReference
    是引用的包装,因此对该字段的任何访问都涉及进一步的指针追踪

  • 内存占用将成倍增加(假设采用压缩的OOPs环境,这对大多数虚拟机都适用):

    • 挥发性ref=4b
    • AtomicReference
      =4b+16b(12b对象头+4b参考字段)
  • AtomicReference
    提供了比volatile引用更丰富的API。您可以通过使用
    AtomicFieldUpdater
    或使用Java 9 a
    VarHandle
    重新获得volatile引用的API。如果你喜欢用剪刀跑步,你也可以直达
    sun.misc.Unsafe
    <代码>原子引用
  • 本身是使用
    不安全
    实现的

    那么,什么时候最好选择一个而不是另一个:

    • 只需要获得/设置?坚持使用易失性字段、最简单的解决方案和最低的开销
    • 需要额外的功能吗?如果这是代码中对性能(速度/内存开销)敏感的部分,请在
      AtomicReference
      /
      AtomicFieldUpdater
      /
      不安全
      之间做出选择,您往往会为性能提升付出可读性和风险。如果这不是一个敏感区域,只需选择
      AtomicReference
      。库编写器通常会根据目标JDK、预期的API限制、内存限制等情况混合使用这些方法

    有时,即使只使用get和set,原子引用也可能是一个不错的选择:

    使用volatile的示例:

    私有易失性状态;
    ...
    公共设置新闻状态(状态新闻状态){
    状态=新闻状态;
    }
    公共无效dosomething条件(){
    if(status.isOk()){
    System.out.println(“Status is ok:+Status);//此处的Status可能不再是ok,因为在此期间,一些名为setNewStatus()。setNewStatus应该同步
    }
    }
    
    带有AtomicReference的实现将免费为您提供一个写时同步拷贝

    私有原子引用状态包装器;
    ...
    公共无效dosomething条件(){
    Status Status=statusWrapper.get();
    if(status.isOk()){
    System.out.println(“Status is ok:+Status);//这里即使同时有人调用setNewStatus(),我们仍然引用旧的
    }
    }
    
    有人可能会说,如果您替换了以下内容,您仍然可以拥有一份合适的副本:

    Status Status=statusWrapper.get();
    
    与:

    Status statusCopy=状态;
    

    然而,第二个更可能在将来的“代码清理”过程中被某人意外删除。

    并且同意更长的答案。我们至少需要一个链接。链接到更长的答案:那么,区别就在于它们的性能。如果没有区别,你就不会建议使用一个而不是另一个。性能基本相同。原子引用增加了复杂性和内存使用。@BT A
    volatile
    字段可以像任何常规字段一样使用,而访问
    AtomicReference
    中的值需要通过
    get
    set
    方法。“JDK源代码是解决此类困惑的最佳方法之一。”=>我不一定同意——javadoc(类的契约)是最好的方式。代码中的内容回答了特定实现的问题,但代码可以更改。例如,hashmap在JDK 6中是不稳定的,但在Java 7中不再是不稳定的。如果您的代码是基于变量是易变的这一事实,那么在升级JDK时它可能会崩溃。。。诚然,这个例子是不同的,但你明白了。这是标准缩写吗?比较和交换=)