同步块可以比Atomics更快吗?

假设有以下两个计数器实现:

class Counter { private final AtomicInteger atomic = new AtomicInteger(0); private int i = 0; public void incrementAtomic() { atomic.incrementAndGet(); } public synchronized void increment() { i++; } } 

乍一看,primefaces应该更快,更具可扩展性。 我相信他们是。 但它们是否比synchronized块一样快? 或者当该规则被破坏时存在某些情况(例如SMP /单CPU机器,不同的CPU ISA,OS等)?

incrementAndGet可以实现为CAS循环。 在高度满足的情况下,对于n个线程,可能导致n -1个线程失败导致O( n )问题。

(对于@Geek:

通常, getAndIncrement可以实现如下:

  int old; do { old = value; } while (!compareAndSet(value, old, old+1)); return old; 

想象一下,你有一个n个线程在同一个primefaces上执行这个代码,它们碰巧是彼此同步的。 第一次迭代确实有效。 只有一个CAS会成功。 其他n -1个线程将重复练习,直到只剩下一个。 所以总工作量是O( n ^ 2)(最差情况)而不是O( n )。 )

话虽如此,获得一个锁将需要做一些类似的事情,并且在严重争用时锁并不是最好的。 在使用需要在get和compareAndSwap之前进行大量计算的CAS循环之前,您不太可能看到锁的优势。

或者当该规则被破坏时存在某些情况(例如SMP /单CPU机器,不同的CPU ISA,OS等)?

我不知道。 (我随时准备纠正……如果有人知道具体的反例。)

然而(这是我的主要观点)没有理论上的理由说明为什么你不能拥有硬件架构或实现不佳的JVM,其中synchronizedatomic类型相同或更快。 (这两种同步forms的相对速度是一个实现问题,因此只能对现有实现进行量化。)

当然,这并不意味着你永远不应该使用synchronizedsynchronized有许多primefaces类无法解决的用例。

它依赖于实现 – 因此最终您需要对您的特定平台/ JVM /配置进行基准测试。

话虽如此,primefaces应该总是更快,原因如下:

  • Atomics的设计使JVM可以利用primefaces机器指令,这是大多数平台可以获得的最快的primefaces操作
  • synchronized使用相对重量级的锁定方案与监视器对象,旨在保护潜在的大块代码。 这种forms的锁定本质上比primefaces操作更复杂,因此您可能期望它具有更高的运行时成本。

正如其他人所说,这是依赖于实现的。 但请记住,如果程序不变量涉及多个变量,则必须使用同步将它们一起更新。 您不能仅仅因为它们是Atomic类型而对两个相关变量进行primefaces操作。 在这种情况下,你唯一的朋友是同步的。

primefaces变量总是会更快。

你可以看到java.util.concurrent包总是使用primefaces变量而不是同步块。