哪个更好”。 AtomicIntegerArray(1/0为真/假)与AtomicBoolean []?

时间:2014-03-06 21:57:39

标签: java multithreading concurrency real-time

我对此非常好奇。如果使用值为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);

您认为哪一个更快更好?

3 个答案:

答案 0 :(得分:11)

  

您认为哪一个更快更好?

有趣的问题。如果你做了很多次循环,那么这个速度可能只是可见的。否则担心它会过早优化。我会选择最干净,最容易维护的模式。

在幕后,两种方法都使用Unsafe.compareAndSwapInt(...),因此性能可能非常相似。由于访问volatile存储空间没有阻止,因此关于冲突。 AtomicBoolean数组肯定会有更多与之关联的对象 - 每个对象都有自己的易失性存储。此外,在AtomicBoolean下,booleanint值存储为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个元素,有效地将错误共享减少到零。