有人知道班级AtomicLongFieldUpdate的任何实际使用情况吗? 我已经阅读了描述,但我还没有完全理解它的含义。 为什么我想知道这个?好奇心和OCPJP准备。
提前致谢。
答案 0 :(得分:5)
您可以考虑以下成本阶梯:
long
:便宜,但对多线程访问不安全volatile long
:更昂贵,更安全的多线程访问,无法进行原子操作AtomicLong
:最昂贵,可安全进行多线程访问,可能进行原子操作(当我说“不安全”或“不可能”时,我的意思是“没有像同步这样的外部机制”。)
在需要多线程访问的情况下,但大多数操作都是简单的读取或写入,只需要几个原子操作,您可以创建一个AtomicLongFieldUpdate
的静态实例,并在原子更新时使用它需要。然后,内存/运行时开销类似于简单的volatile
变量,除了普通AtomicLong
操作的顺序(或稍微贵一点)的原子操作。
答案 1 :(得分:2)
是否有人知道
AtomicLongFieldUpdate
课程的任何实际使用情况?
我自己从未使用过这个类,但是在我的工作区中使用它时,我看到了几个“真实”的实例:
com.google.common.util.concurrent.AtomicDouble
使用它以原子方式修改其内部volatile long
字段,该字段使用double
存储来自Number.doubleToRawLongBits(...)
的位。非常酷。
net.sf.ehcache.Element
使用它以原子方式更新hitCount
字段。
我已阅读说明,但我还没有完全理解它的含义。
它基本上提供与AtomicLong
相同的功能,但是在另一个类的本地字段上。 AtomicLongFieldUpdate
的内存负载小于AtomicLong
,因为您为每个字段配置了一个更新实例,因此内存开销较低,但反射的CPU开销较大(尽管可能很小)。 p>
javadocs说:
此类设计用于原子数据结构,其中同一节点的多个字段独立地受原子更新。
当然,但我只使用多个Atomic*
字段。我使用该类的唯一原因是,如果有一个我无法改变的现有类,我想以原子方式增加。
答案 2 :(得分:1)
您将使用例如AtomicLongFieldUpdater支持AtomicLong只是为了降低堆成本。在内部,两者在compareAndSet级别上的工作几乎完全相同,它们最后都使用sun.misc.Unsafe。
考虑你有一个初始化1000k次的某个类。使用AtomicLong,您可以创建1000k AtomicLongs。另一方面,使用AtomicLongFieldUpdater,您可以创建1个CONSTANT AtomicLongFieldUpdater和1000k长基元,这当然不需要太多堆空间。
答案 3 :(得分:0)
当然。我最近一直在阅读Alibaba Druid。我发现 AtomicLongFieldUpdater
在这个项目中被广泛使用。
// stats
private volatile long recycleErrorCount = 0L;
private volatile long connectErrorCount = 0L;
protected static final AtomicLongFieldUpdater<DruidDataSource> recycleErrorCountUpdater
= AtomicLongFieldUpdater.newUpdater(DruidDataSource.class, "recycleErrorCount");
protected static final AtomicLongFieldUpdater<DruidDataSource> connectErrorCountUpdater
= AtomicLongFieldUpdater.newUpdater(DruidDataSource.class, "connectErrorCount");
如上定义,属性 recycleErrorCount
和 connectErrorCount
用于计算错误发生的次数。
相当多的 DataSource
(持有上述属性的类)将在应用程序生命周期内创建,在这种情况下,使用 ALFU
明显比使用 AtomicLong
减少堆空间消耗。
答案 4 :(得分:-2)
Atomics通常用于并行编程。
在工作窃取模式下,它只支持异步,完成,异步同步,隔离和原子变量。
您可以将原子视为安全保护,免受数据争用以及并行编程中需要关注的其他问题的影响。