我对此非常好奇。如果使用值为0和1的AtomicIntegerArray,则可以完成AtomicBoolean数组的相同操作。例如:
final AtomicIntegerArray array1 = new AtomicIntegerArray(10);
array1.compareAndSet(3, 0, 1); // 0 = false and 1 = true
// exactly the same thing of:
final AtomicBoolean[] array2 = new AtomicBoolean[10];
for(int i = 0; i < array2.length; i++)
array2[i] = new AtomicBoolean(false);
array2[3].compareAndSet(false, true);
您认为哪一个更快更好?
答案 0 :(得分:11)
您认为哪一个更快更好?
有趣的问题。如果你做了很多次循环,那么这个速度可能只是可见的。否则担心它会过早优化。我会选择最干净,最容易维护的模式。
在幕后,两种方法都使用Unsafe.compareAndSwapInt(...)
,因此性能可能非常相似。由于访问volatile
存储空间没有阻止,因此不关于冲突。 AtomicBoolean
数组肯定会有更多与之关联的对象 - 每个对象都有自己的易失性存储。此外,在AtomicBoolean
下,boolean
将int
值存储为AtomicIntegerArray
,因此无法节省费用。
我的直觉告诉我使用AtomicIntegerArray in 4224 millis
AtomicBoolean[] in 3546 millis (always a little bit faster)
。您编写的代码较少,这通常意味着更多依赖JDK来做正确的事情。要弄明白,您必须在生产架构上测试一些大量的迭代才能确定。我怀疑差异可以忽略不计,很难衡量。
不是一个很好的答案,但希望在这里有所帮助。
修改强>
所以我只是进行了一些测试,我看不出任何明显的差异。这是我的little test program。它使用了100个线程并运行了1000万次迭代,它们彼此相差0-10%。正如@mttdbrd指出的那样,这绝不是一个“现实生活”测试。只有在真正知道是否存在差异之前,才能在生产过程中使用代码实际运行。
修改强>
在调整我的程序以确保我根据@ mttdbrd的文档预热热点编译器并更改程序以便能够更好地调整条目数之后,我看到了一些有趣的结果。
数组中有1000个元素:
AtomicIntegerArray in 26506 millis
AtomicBoolean[] in 13263 millis (much faster)
但阵列中有10个元素:
{{1}}
另请注意速度差异。这是有道理的,因为有更多的线程争用。 100个线程更可能需要旋转10个元素而不是1000个。
这是什么意思?如果您从一个更改为另一个,则每个操作最多可以节省 1 纳秒 。威力。因此,您应该选择最干净,最容易维护的模式,而不是担心两者的表现。
答案 1 :(得分:3)
实际上正在观看AtomicIntegerArray的实现
http://fuseyism.com/classpath/doc/java/util/concurrent/atomic/AtomicIntegerArray-source.html
似乎我认为它的管理更受关注。
它不使用对象来存储值,使其在内存中更有效。 实际上它使用一个简单的int []然后以安全的方式访问它们。
所以我认为如果你需要使用许多AtomicInteger,最好使用AtomicIntegerArray。
AtomicIntegerArray: 使用Unsafe类对AtomicIntegerArray中的单个int []进行原子访问
的AtomicBoolean []: 数组的每个对象都有它的对象(本身)来进行原子访问
因此,我希望在具有AtomicBoolean []的繁重并发线程环境中获得更好的性能,并且内存消耗比AtomicIntegerArray更多。
答案 2 :(得分:1)
我会说两者都具有同样的表现力,除非有很多争议。那(作为格雷的基准测试),AtomicBoolean[]
轻松胜过AtomicIntegerArray
。缺少的是解释:
虽然AtomicIntegerArray
将所有int
放在彼此旁边,因为它在内部int[]
上运行,而AtomicBoolean[]
是包含<{1}}的数组int
EM>物体。这些对象增加了少量(8或12)字节的开销,因此底层的int
没有紧密包装。
因此它们跨越不同数量的缓存行,此处False sharing开始发挥作用。由于缓存行通常为64字节,因此new AtomicIntegerArray(10)
的整个数据适合它(除非它开始未对齐,然后使用两个缓存行)。这意味着100%的错误共享概率,即就像所有线程都满足于单个变量一样。
由于AtomicBoolean[]
的开销,我们得到160字节而不是40字节,因此错误分享的次数要少得多。
我猜Gray的基准测试有很多开销(%
操作和条件),真正的速度差异会更大。
这并不意味着AtomicIntegerArray
不好。只是如果真的非常争议的话,不应该像这样使用它。简单的解决方案是分配一个更大的数组并仅使用每个第16个元素,有效地将错误共享减少到零。