Tuesday, December 09, 2008

什么时候应该避免使用Java中的AtomicInteger类

对于多线程中的计数器,我们通常推荐使用j.u.c中的AtomicInteger来替代一个用锁保护的int类型的变量。例如从:

private int value;

synchronized public void increment() {

value++;

}


变动到:

AtomicInteger ai = new AtomicInteger();

public void increment1(){

ai.incrementAndGet();

}


由于synchronized关键字利用this对象同步,而this对象可能还被用于其他同步目的,因此相对AtomicInteger有较多的机会造成线程之间的相互等待。而AtomicInteger本身有一个小的同步块,因而不和其他利用this对象同步的线程竞争,通常会更好一些。而且AtomicInteger的很多方法都是lock-free的,对Scalability有较大的好处。

不过在一些情况,我们还是应该利用synchronized而不是Atomic包。首先,如果我们程序中线程数目较少,或者该计数器不是一个热点时,用锁的程序和AtomicInteger的程序性能没有什么差别。为了节约内存,我们可以采用基于synchronized的版本或者AtomicIntegerFieldUpdater。其次,如果有多个计数器需要操作,那么在一个synchronized块中进行所有的操作比采用多个Atomic对象要好。这点从代码路径上就可以看出。如果线程之间不发生冲突,那么一个synchronized块和一个atomic对象一个CAS操作。如果一个synchronized块处理了多个需要保护的操作,那么就节约了CAS操作的数目,因而具有较高的性能。

0 comments: