前言:
JDK1.5之后的java.util.concurrent.atomic包里,多了一批原子處理類(lèi)壶硅。AtomicBoolean、AtomicInteger、AtomicLong编矾、AtomicReference。主要用于在高并發(fā)環(huán)境下的高效程序處理,來(lái)幫助我們簡(jiǎn)化同步處理.
AtomicInteger:
AtomicInteger馁害,一個(gè)提供原子操作的Integer的類(lèi)窄俏。在Java語(yǔ)言中,++i和i++操作并不是線程安全的碘菜,在使用的時(shí)候凹蜈,不可避免的會(huì)用到synchronized關(guān)鍵字。而AtomicInteger則通過(guò)一種線程安全的加減操作接口忍啸。
我們先來(lái)看看AtomicInteger給我們提供了什么接口:
public final int get() //獲取當(dāng)前的值
public final int getAndSet(int newValue)//獲取當(dāng)前的值仰坦,并設(shè)置新的值
public final int getAndIncrement()//獲取當(dāng)前的值,并自增
public final int getAndDecrement() //獲取當(dāng)前的值计雌,并自減
public final int getAndAdd(int delta) //獲取當(dāng)前的值悄晃,并加上預(yù)期的值
下面通過(guò)兩個(gè)簡(jiǎn)單的例子來(lái)看一下 AtomicInteger 的優(yōu)勢(shì)在哪:
普通線程同步:
class Test2 {
private volatile int count = 0;
public synchronized void increment() {
count++; //若要線程安全執(zhí)行執(zhí)行count++,需要加鎖
}
public int getCount() {
return count;
}
}
使用AtomicInteger:
class Test2 {
private AtomicInteger count = new AtomicInteger();
public void increment() {
count.incrementAndGet();
}
//使用AtomicInteger之后白粉,不需要加鎖传泊,也可以實(shí)現(xiàn)線程安全。
public int getCount() {
return count.get();
}
}
從上面的例子中我們可以看出:使用AtomicInteger是非常的安全的.而且因?yàn)锳tomicInteger由硬件提供原子操作指令實(shí)現(xiàn)的鸭巴。在非激烈競(jìng)爭(zhēng)的情況下眷细,開(kāi)銷(xiāo)更小,速度更快鹃祖。
我們來(lái)看看AtomicInteger是如何使用非阻塞算法來(lái)實(shí)現(xiàn)并發(fā)控制的:
AtomicInteger的關(guān)鍵域只有一下3個(gè):
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset (AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) {
throw new Error(ex);
}
}
private volatile int value;
這里溪椎, unsafe是java提供的獲得對(duì)對(duì)象內(nèi)存地址訪問(wèn)的類(lèi),注釋已經(jīng)清楚的寫(xiě)出了恬口,它的作用就是在更新操作時(shí)提供“比較并替換”的作用校读。實(shí)際上就是AtomicInteger中的一個(gè)工具。
valueOffset是用來(lái)記錄value本身在內(nèi)存的便宜地址的祖能,這個(gè)記錄歉秫,也主要是為了在更新操作在內(nèi)存中找到value的位置,方便比較养铸。
注意:value是用來(lái)存儲(chǔ)整數(shù)的時(shí)間變量雁芙,這里被聲明為volatile轧膘,就是為了保證在更新操作時(shí),當(dāng)前線程可以拿到value最新的值(并發(fā)環(huán)境下兔甘,value可能已經(jīng)被其他線程更新了)谎碍。
這里,我們以自增的代碼為例洞焙,可以看到這個(gè)并發(fā)控制的核心算法:
/**
*Atomicallyincrementsbyonethecurrentvalue.
*
*@returntheupdatedvalue
*/
publicfinalintincrementAndGet(){
for(;;){
//這里可以拿到value的最新值
intcurrent=get();
intnext=current+1;
if(compareAndSet(current,next))
returnnext;
}
}
publicfinalbooleancompareAndSet(intexpect,intupdate){
//使用unsafe的native方法蟆淀,實(shí)現(xiàn)高效的硬件級(jí)別CAS
returnunsafe.compareAndSwapInt(this,valueOffset,expect,update);
}
優(yōu)點(diǎn)總結(jié):
最大的好處就是可以避免多線程的優(yōu)先級(jí)倒置和死鎖情況的發(fā)生,提升在高并發(fā)處理下的性能澡匪。
擴(kuò)展鏈接:http://www.ibm.com/developerworks/cn/java/j-jtp11234/