aqs clh java_【Java并发编程实战】----- AQS(一):简介
在前面博客中,LZ講到了ReentrantLock、ReentrantReadWriteLock、Semaphore、CountDownLatch,他們都有各自獲取鎖的方法,同時相對于Java的內(nèi)置鎖,他們具有明顯的優(yōu)勢:花最小的空間開銷創(chuàng)建鎖、最少的時間開銷獲得鎖、使用更加方便靈活。
參考Java的內(nèi)置鎖,對于JUC同步器而言,他應(yīng)該具備兩個最基本的功能:獲取鎖,釋放鎖。其中獲取鎖應(yīng)該是先判斷當(dāng)前狀態(tài)是否可以獲取,如果不可以獲取則處于阻塞狀態(tài),釋放應(yīng)該是釋放后修改狀態(tài),讓其他線程能夠得到該鎖(喚醒其他線程),如下:
lock:while(state){ // getLock(); //獲取鎖
return currentThread; //返回當(dāng)前線程
}
release:
updateState();//修改狀態(tài)
notify other thread; //喚醒其他線程
我們知道,在JUC中,各個同步器獲取鎖和釋放鎖的方法都不相同,比如:lock.lock()、Semaphore.acquire()、 CountDownLatch.await()等等,假如他們都各自實現(xiàn)各自的方法,那么這個JUC框架頂多只能算一個中下等的框架設(shè)計了。這是AQS騰空出世,AQS作為一個核心的處理框架,他提供了大量的同步操作,同時用戶還可以在此類的基礎(chǔ)上進(jìn)行自定義,實現(xiàn)自己的同步器。其主要框架如下:
從上圖可以看出AQS是JUC同步器的基石。下面就AQS涉及的技術(shù)原理簡單闡述下,以后會對其做詳細(xì)的說明。
1、狀態(tài)位state
AQS用的是一個32位的整型來表示同步狀態(tài)的,它是用volatile修飾的:
private volatile int state;
在互斥鎖中它表示著線程是否已經(jīng)獲取了鎖,0未獲取,1已經(jīng)獲取了,大于1表示重入數(shù)。同時AQS提供了getState()、setState()、compareAndSetState()方法來獲取和修改該值:
protected final intgetState() {returnstate;
}protected final void setState(intnewState) {
state=newState;
}protected final boolean compareAndSetState(int expect, intupdate) {return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
這些方法需要java.util.concurrent.atomic包的支持,采用CAS操作,保證其原則性和可見性。
2、CLH同步隊列
在前面就提到過AQS內(nèi)部維護(hù)著一個FIFO的CLH隊列,所以AQS并不支持基于優(yōu)先級的同步策略。至于為何要選擇CLH隊列,主要在于CLH鎖相對于MSC鎖,他更加容易處理cancel和timeout,同時他具備進(jìn)出隊列快、無所、暢通無阻、檢查是否有線程在等待也非常容易(head != tail,頭尾指針不同)。當(dāng)然相對于原始的CLH隊列鎖,ASQ采用的是一種變種的CLH隊列鎖:
1、原始CLH使用的locked自旋,而AQS的CLH則是在每個node里面使用一個狀態(tài)字段來控制阻塞,而不是自旋。
2、為了可以處理timeout和cancel操作,每個node維護(hù)一個指向前驅(qū)的指針。如果一個node的前驅(qū)被cancel,這個node可以前向移動使用前驅(qū)的狀態(tài)字段。
3、head結(jié)點使用的是傀儡結(jié)點。
3、共享鎖、互斥鎖
在AQS維護(hù)的CLH隊列鎖中,每個節(jié)點(Node)代表著一個需要獲取鎖的線程。該Node中有兩個常量SHARE、EXCLUSIVE。其中SHARE代表著共享模式,EXCLUSIVE代表著獨占模式。
static final classNode {/**Marker to indicate a node is waiting in shared mode*/
static final Node SHARED = newNode();/**Marker to indicate a node is waiting in exclusive mode*/
static final Node EXCLUSIVE = null;/
}
其中共享模式是允許多個線程可以獲取同一個鎖,而獨占模式則一個鎖只能被一個線程持有,其他線程必須要等待。
4、阻塞、喚醒
我們知道在使用Java內(nèi)置鎖時,可以使用wait、notify方法來阻塞、喚醒線程,但是AQS并沒有采用該模式,而是通過LockSupport.park() 和 LockSupport.unpark() 的本地方法來實現(xiàn)線程的阻塞和喚醒。
總結(jié)
以上是生活随笔為你收集整理的aqs clh java_【Java并发编程实战】----- AQS(一):简介的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: javascript在HTML中使用方法
- 下一篇: html表单显示提示,html侧栏对应表