Java 与AtomicReference等效,但没有易失性同步成本
什么是等效的:Java 与AtomicReference等效,但没有易失性同步成本,java,reference,Java,Reference,什么是等效的: AtomicReference<SomeClass> ref = new AtomicReference<SomeClass>( ... ); AtomicReference=new-AtomicReference(…); 但是没有同步成本。请注意,我确实希望将引用包装到另一个对象中 我已经看过扩展引用抽象类的类,但是在所有的选择中我有点迷失了方向 我需要一些真正简单的东西,不是脆弱的,不是幻影的,也不是除了一个以外的所有其他参考资料。我应该使用哪个类
AtomicReference<SomeClass> ref = new AtomicReference<SomeClass>( ... );
AtomicReference=new-AtomicReference(…);
但是没有同步成本。请注意,我确实希望将引用包装到另一个对象中
我已经看过扩展引用抽象类的类,但是在所有的选择中我有点迷失了方向
我需要一些真正简单的东西,不是脆弱的,不是幻影的,也不是除了一个以外的所有其他参考资料。我应该使用哪个类?原子引用没有同步开销。从软件包的描述中: 支持单变量无锁线程安全编程的小型类工具包 编辑
根据您对原始帖子的评论,您似乎以非标准的方式使用了术语“同步成本”来表示线程本地缓存刷新。在大多数体系结构上,读取
易失性几乎与读取非易失性值一样便宜。对共享变量的任何更新都需要至少刷新该变量的缓存(除非您要完全取消线程本地缓存)。如果您只是试图在对象中存储引用,那么没有任何东西比java.util.concurrent.atomic中的类更便宜(性能方面)。你不能创建一个带有字段的类吗?因为字段是一个很强的引用,应该可以实现你想要的
您不应该创建一个StrongReference类(因为这样做很愚蠢),而应该演示它
public class StrongReference{
Object refernece;
public void set(Object ref){
this.reference =ref;
}
public Object get(){
return this.reference;
}
}
AtomicReference没有传统同步部分意义上的同步成本。它被实现为非阻塞,这意味着等待“获取锁”的线程不是上下文切换的,这使得它在实践中非常快。可能对于同时更新单个引用,您找不到更快的方法。所有提供的扩展引用的类都附加了一些特殊功能,从原子CA到允许收集引用的对象,尽管对象仍然存在引用
您可以按照说明创建自己的StringReference(或使用长度==1的数组),但是如果您仍然想使用原子引用,但又不想承担使用lazySet的易失性写操作的成本,那么就没有那么多的用途了
写操作不会像普通的易失性写操作那样发出内存屏障,但是get仍然调用易失性负载(相对便宜)
AtomicReference ref=新的AtomicReference();
参考懒散者(某类);
如果希望引用没有线程安全性,可以使用一个数组
MyObject[] ref = { new MyObject() };
MyObject mo = ref[0];
ref[0] = n;
我想你想要的是:
public class MyReference<T>{
T reference;
public void set(T ref){
this.reference =ref;
}
public T get(){
return this.reference;
}
}
公共类MyReference{
T参考;
公共无效集(T参考){
this.reference=ref;
}
公共部门得不到{
返回此.reference;
}
}
您可以考虑添加委托均衡器()、HASCODE()和 < P>如果您的值是不可变的,看起来是一个不错的选择。 < P>自java 9以来,您现在可以使用<代码> AtomicReference。SETIVE()/<代码>和<代码> AtomicReference .GETSLIVE()/<代码> < /P>
setPlain上的JavaDoc
:
“将值设置为newValue,内存语义设置为变量被声明为非易失性和非最终变量。”使用java.util.并发原子为了共享对象的引用,我觉得原子引用也是错误的。除了“原子性成本”之外,AtomicReference还充满了与您的用例无关的方法,可能会给用户带来错误的期望。
但是我还没有在JDK中遇到这样一个等价的类
以下是您的选项摘要-选择最适合您的选项:
- 自写值容器,如其他答案中建议的
StrongReference
或MyReference
- 来自ApacheCommonsLang
- 长度为1的数组或大小为1的数组
- 自Java9以来的
AtomicReference
我认为您错过了原子参考中使用的“volatile”。volatile具有同步成本,即使未使用关键字“synchronized”。这可能是您困惑的根源。volatile和synchronized在语义和成本上有很大的区别。@NoozNooz42-volatile
强制只在内存中更新volatile变量;使用同步
,需要更新所有线程本地缓存变量volatile
往往比synchronized
便宜得多。有关详细信息,请参阅。@Ted Hopp这不完全正确。在写入易失性字段之前发生的所有写入操作将对随后读取该易失性字段的任何线程可见。但是你是对的,一个易失性写入比一个同步写入少1/3。@JohnVint-我很好奇-你从哪里得到了~1/3的统计数据?等等,原子引用是同步的?你从哪里推断?这将与它背后的整个想法相矛盾。@Viruzzo:改写了问题。。。我想避免由于使用volatile关键字而导致的同步成本。每个人都需要了解同步!=synchronized
,它实际上可能是synchronized
,但同步只是意味着某种形式的互斥/内存保证。相对于非同步/线程安全的obejcts,原子引用是昂贵的。1.即线程同步,我们关于原子参考和同步成本的讨论涉及数据同步(位于您提供的链接中)。更重要的是,您可以阅读cahce同步。根据系统的不同,易失性写入可以使用缓存一致性(这是一种非阻塞的同步形式)。同步应用于非阻塞算法。你可以读赫利希的爸爸
public class MyReference<T>{
T reference;
public void set(T ref){
this.reference =ref;
}
public T get(){
return this.reference;
}
}