初识AOS --------AOS学习笔记系列
AQS構建鎖和同步器的框架
AQS原理:
共享資源空閑時,分配給當前請求線程,并鎖定資源。
不空閑時,請求線程加入CLH隊列(FIFO,CAS修改同步狀態),其能夠實現線程阻塞以及喚醒功能。 AQS對資源共享的方式: Exclusive(獨占)
只有一個線程能執行,如RenntrantLock。分為公平鎖(按照隊列中的順序)和非公平鎖(搶到就是誰的) Share(共享)
如Semaphore
自定義同步器
1.繼承AbstractQueuedSynchronizer并重寫指定的方法。
2.將AQS組合在自定義同步組件實現,并調用模板方法,模板方法會調用使用者重寫方法 需要重寫的方法: isHeldExclusively() 線程是否在獨占資源 tryAcquire(int) 獨占方法,嘗試獲取資源
tryRelease(int) 獨占資源,嘗試釋放資源
tryAcquireShared(int) 共享資源,嘗試獲取資源
tryReleaseShared(int) 共享資源,嘗試釋放資源
AQS組件總結
Semaphore(信號量)-允許多個線程同時訪問
CountDownLatch(倒計時)協調多個進程之間的同步。控制線程等待,直到某一線程結束
CyclicBarrier(循環柵欄)讓一組線程達到屏障時被阻塞,直到最后一個線程達到屏障是柵欄才會打開
tryAcquire()嘗試直接去獲取資源,如果成功則直接返回(這里體現了非公平鎖,每個線程獲取鎖時會嘗試直接搶占加塞一次,而CLH隊列中可能還有別的線程在等待);
addWaiter()將該線程加入等待隊列的尾部,并標記為獨占模式;
acquireQueued()使線程阻塞在等待隊列中獲取資源,一直獲取到資源后才返回。如果在整個等待過程中被中斷過,則返回true,否則返回false。
tryAcquire(int) tryAcquire方法是為了去重寫方法
此方法嘗試去獲取獨占資源。如果獲取成功,則直接返回true,否則直接返回false。這也正是tryLock()的語義,還是那句話,當然不僅僅只限于tryLock()。如下是tryAcquire()的源碼:
1 protected boolean tryAcquire(int arg) { 2 throw new
UnsupportedOperationException(); 3 }
模板方法 獨享模式下 一個線程同一時間內只允許獲取一把鎖
鉤子方法
通過acquire和acquireShared獲取鎖,通過release和releaseShared釋放鎖
獨占式和共享式的區別總結
共享式獲取與獨占式獲取最大的區別就是同一時刻能否有多個線程同時獲取到同步狀態。
共享式訪問資源時,同一時刻其他共享式的訪問會被允許。獨占式訪問資源時,同一時刻其他訪問均被阻塞。
AQS都提供了子類實現的鉤子方法,獨占式的代表方法有:tryAcquire和tryRelease以及isHeldExclusively方法,共享式的代表方法有:tryAcquireShared和tryReleaseShared方法。
AQS中獲取操作和釋放操作的標準形式: boolean acquire() throws InterruptedException{
while( 當前狀態不允許獲取操作 ){
if( 需要阻塞獲取請求){
如果當前線程不在隊列中,則將其插入隊列
阻塞當前線程
}else{
返回失敗
}
}
可能更新同步器的狀態
如果線程位于隊列中,則將其移除隊列
返回成功 }
圖源:《并發編程的藝術》下圖是獨占式同步狀態獲取的流程
當某個線程爭奪同步資源失敗之后,他們都會將線程包裝為節點,并加入CLH同步隊列的隊尾,并保持自旋,一個是addWaiter(Node.EXCLUSIVE),一個是addWaiter(Node.EXCLUSIVE)。
同步隊列中的線程在自旋時會判斷其前驅節點是否為首節點,如果是首節點node.predecessor() ==
head,他們都會嘗試獲取同步狀態,只不過: 獨占式獲取狀態成功后,只會出隊一個節點。
共享式獲取狀態成功后,除了出隊一個節點,還會喚醒后面的節點。
線程執行完邏輯之后,他們都會釋放同步狀態,釋放之后將會unparkSuccessor(h)喚醒其后可被喚醒的某個后繼節點。
總結
以上是生活随笔為你收集整理的初识AOS --------AOS学习笔记系列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 细胞膜包覆的负载二氧化锰药物|透明质酸修
- 下一篇: Modulation of Lipid