Java并發(fā)編程之原子操作類詳情
JUC包提供了一系列的原子性操作類,這些類都是使用非阻塞算法CAS實(shí)現(xiàn)的,相比使用鎖實(shí)現(xiàn)原子性操作者在性能上有很大提升。JUC包中含有AtomicInteger、AtomicLong、AtomicBoolean,它們的原理類似。下面我們以AtomicLong為例來(lái)講解。
我們先來(lái)看一下部分源碼:
public class AtomicLong extends Number implements java.io.Serializable {
private static final long serialVersionUID = 1927816293512124184L;
//1.獲取Unsafe類實(shí)例
private static final Unsafe unsafe = Unsafe.getUnsafe();
//2.存放value的偏移量
private static final long valueOffset;
static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
//3.用于判斷是否支持Long類型無(wú)鎖CAS
private static native boolean VMSupportsCS8();
static {
try {
//4.獲取value在AtomicLong中的偏移量
valueOffset = unsafe.objectFieldOffset
(AtomicLong.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
//5.實(shí)際變量值
private volatile long value;
/**
* Creates a new AtomicLong with the given initial value.
*
* @param initialValue the initial value
*/
public AtomicLong(long initialValue) {
value = initialValue;
}
············省略部分代碼·············
}
上面代碼中,代碼1處通過(guò)Unsafe.getUnsafe()獲取到Unsafe類的實(shí)例(因?yàn)锳tomicLong類是在rt.jar包下面的,AtomicLong類就是通過(guò)Bootstarp類加載器進(jìn)行加載的)。代碼5處,value被聲明為volatile類型,保證內(nèi)存的可見(jiàn)性。通過(guò)代碼2,4獲取value變量在AtomicLong類中的偏移量。
接下來(lái)介紹一下AtomicLong中的主要函數(shù):
- 遞增和遞減代碼
//調(diào)用unsafe方法,設(shè)置value=value+1后,返回原始的值
public final long getAndIncrement() {
return unsafe.getAndAddLong(this, valueOffset, 1L);
}
//調(diào)用unsafe方法,設(shè)置value=value-1后,返回原始的值
public final long getAndDecrement() {
return unsafe.getAndAddLong(this, valueOffset, -1L);
}
//調(diào)用unsafe方法,設(shè)置value=value+1后,返回遞增后的值
public final long incrementAndGet() {
return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;
}
//調(diào)用unsafe方法,設(shè)置value=value-1后,返回遞減后的值
public final long decrementAndGet() {
return unsafe.getAndAddLong(this, valueOffset, -1L) - 1L;
}
上面的四個(gè)函數(shù)內(nèi)部都是通過(guò)調(diào)用Unsafe的getAndAddLong方法來(lái)實(shí)現(xiàn)操作,這個(gè)函數(shù)是個(gè)原子性操作,這里第一個(gè)參數(shù)是AtomicLong實(shí)例的引用的,第二個(gè)參數(shù)是value變量在AtomicLong的偏移值,第三個(gè)參數(shù)是要設(shè)置的第二個(gè)變量的值。
其中g(shù)etAndIncrement()方法在JDK7中實(shí)現(xiàn)邏輯為:
public final long getAndIncrement() {
while(true) {
long current = get();
long next = current + 1;
if (compareAndSet(current, next))
return current;
}
}
如上代碼中,每個(gè)線程是先拿到變量的當(dāng)前值(由于value是volatile變量,所以這是獲取的最新值),然后在工作內(nèi)存中對(duì)其進(jìn)行增1操作,而后使用CAS修改變量的值,如果設(shè)置失敗,則循環(huán)繼續(xù)嘗試,直到設(shè)置成功。
JDK8中的邏輯為:
public final long getAndIncrement() {
retrturn unsafe.getAndAddLong(this, valueOffset, 1L);
}
其中JDK8中的unsafe.getAndAddLong的代碼為:
public final long getAndAddLong(Object var1, long var2, long var4) {
long var6;
do {
var6 = this.getLongVolatile(var1, var2);
} while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4));
return var6;
}
從中可以看到,JDK7中的AtomicLong中循環(huán)邏輯已經(jīng)被JDK8中的原子操作類Unsafe內(nèi)置了。
- boolean compareAndSet(long expect,long update)
public final boolean compareAndSet(long expect,long update)
{
return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
}
函數(shù)在內(nèi)部調(diào)用了unsafe.compareAndSwapLong方法。如果原子變量中的value值等于expect,則使用update值更新該值并返回true,否則返回false。
到此這篇關(guān)于Java并發(fā)編程之原子操作類詳情的文章就介紹到這了,更多相關(guān)Java 原子操作類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決Mybatis?mappe同時(shí)傳遞?List?和其他參數(shù)報(bào)錯(cuò)的問(wèn)題
在使用MyBatis時(shí),如果需要傳遞多個(gè)參數(shù)到SQL中,可以遇到參數(shù)綁定問(wèn)題,解決方法包括使用@Param注解和修改mapper.xml配置,感興趣的朋友跟隨小編一起看看吧2024-09-09
Spring Boot對(duì)Future模式的支持詳解
這篇文章主要給大家介紹了關(guān)于Spring Boot對(duì)Future模式的支持的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用spring boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧2019-01-01
Java實(shí)現(xiàn)獲取小程序帶參二維碼并保存到本地
這篇文章主要介紹了Java實(shí)現(xiàn)獲取小程序帶參二維碼并保存到本地,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10
Java動(dòng)態(tài)規(guī)劃之硬幣找零問(wèn)題實(shí)現(xiàn)示例
本文主要介紹了Java動(dòng)態(tài)規(guī)劃之硬幣找零問(wèn)題實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
idea啟動(dòng)Tomcat時(shí)控制臺(tái)亂碼的解決方法(親測(cè)有效)
最近在idea中啟動(dòng)tomcat出現(xiàn)控制臺(tái)亂碼問(wèn)題,嘗試了很多方法,最后終于解決了,所以下面這篇文章主要給大家介紹了關(guān)于idea啟動(dòng)Tomcat時(shí)控制臺(tái)亂碼的解決方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07
IDEA使用properties配置文件進(jìn)行mysql數(shù)據(jù)庫(kù)連接的教程圖解
Properties類是 鍵和值均為字符串的可以永久存儲(chǔ)到文件中的key-value集合。這篇文章主要介紹了IDEA使用properties配置文件進(jìn)行mysql數(shù)據(jù)路連接 ,需要的朋友可以參考下2018-10-10

