我对此很好奇。如果使用值为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);你认为哪个更快更好?
发布于 2014-03-06 22:14:08
你认为哪个更快更好?
有趣的问题。这个速度可能只有在你做一些非常多的循环时才是可见的。否则,担心它就像是过早的优化。我会选择最干净和最容易维护的模式。
在幕后,两种方法都使用Unsafe.compareAndSwapInt(...),因此性能可能非常相似。由于对volatile存储的访问没有阻塞,所以这与冲突无关。AtomicBoolean数组肯定会有更多与其关联的对象--每个对象都有自己的易失性存储。此外,在幕后,AtomicBoolean将boolean值存储为int,这样就不会节省任何费用。
我的直觉告诉我要使用AtomicIntegerArray。编写的代码较少,这通常意味着更多地依赖JDK来做正确的事情。要想弄清楚这一点,您必须在生产架构上测试大量迭代才能确定。我怀疑这种差别是可以忽略不计的,而且很难测量。
不是一个很好的答案,但希望这里有帮助。
编辑:
所以我只是做了一些测试,我看不出有什么明显的差别。这是我的小测试程序。它使用了100个线程,运行了1000万次迭代,它们之间的距离在0-10%以内。正如@mttdbrd所指出的,这绝不是一个“现实生活”测试。只有在生产过程中使用实际像它那样工作的代码时,才能真正了解两者之间是否有区别。
编辑:
好的,在调整我的程序以确保我将hotspot编译器放在@mttdbrd的文档中,并更改程序以便更好地调优条目的数量之后,我看到了一些有趣的结果。
数组中有1000个元素:
AtomicIntegerArray in 4224 millis
AtomicBoolean[] in 3546 millis (always a little bit faster)但是,在数组中有10个元素:
AtomicIntegerArray in 26506 millis
AtomicBoolean[] in 13263 millis (much faster)还注意到了速度的差异。这是有意义的,因为有更多的线程争用。100个线程更可能需要使用10个元素而不是1000个元素来旋转。
这是什么意思?如果您从一次更改到另一次,您最多可以节省每次操作的1 纳秒。也许吧。因此,与其担心两者的性能,不如选择最干净、最容易维护的模式。
发布于 2014-03-06 22:02:10
实际监视AtomicIntegerArray的实现
http://fuseyism.com/classpath/doc/java/util/concurrent/atomic/AtomicIntegerArray-source.html
它似乎是用比我想的更多的注意力来管理的。
它不使用对象来存储值,从而使其在内存中更有效。实际上,它使用一个简单的int[],然后以一种安全的方式访问它们。
因此,我认为,如果您需要使用许多AtomicInteger,最好使用AtomicIntegerArray。
AtomicIntegerArray:使用不安全类对AtomicIntegerArray中的单个int[]进行原子访问
AtomicBoolean[]:数组的每个对象都有它的对象(本身)来进行原子访问
因此,我希望在具有AtomicBoolean[]的重并发线程环境中获得更好的性能,并且比AtomicIntegerArray占用更多的内存。
发布于 2015-05-24 10:32:01
我想说的是,这两者都是同样的表演,除非激烈的竞争。正如格雷的基准显示的那样,AtomicBoolean[]轻松战胜了AtomicIntegerArray。缺少的是这样的解释:
当AtomicIntegerArray在其内部int[]上操作时,将所有int的位置放在一起,而AtomicBoolean[]是一个包含对象的int数组。这些对象增加了很少(8或12)字节的开销,这样底层的int就不会被严格打包。
因此它们跨越了不同数量的缓存线,在这里, 虚假共享 起作用。由于缓存线通常是64字节,所以new AtomicIntegerArray(10)的全部数据都符合它(除非它开始对齐,然后使用两条缓存线)。这意味着错误共享的概率为100%,也就是说,它就像单个变量满足所有线程一样。
使用AtomicBoolean[]的开销,我们可以得到大约160个字节,而不是40个字节,因此更少的错误共享。
我猜格雷的基准有相当多的开销(%操作和条件),实际的速度差异会更大。
这并不意味着AtomicIntegerArray是坏的。只是如果真的激烈竞争的话,就不应该这样使用。简单的解决方案是分配一个大得多的数组,并且只使用每16个元素,有效地将错误共享减少到零。
https://stackoverflow.com/questions/22236928
复制相似问题