摘要:我在面試題中也見過他的身影,但一直不知道是什么東西。直到當前線程被或者獲取到資源,結(jié)束。簡簡單單把過一遍明天就看顯式鎖實現(xiàn)咯參考資料如果文章有錯的地方歡迎指正,大家互相交流。為了大家方便,剛新建了一下群,大家也可以去交流交流。
前言
回顧前面:
多線程三分鐘就可以入個門了!
Thread源碼剖析
多線程基礎必要知識點!看了學習多線程事半功倍
Java鎖機制了解一下
只有光頭才能變強!
本來我是打算在這章節(jié)中寫Lock的子類實現(xiàn)的,但看到了AQS的這么一個概念,可以說Lock的子類實現(xiàn)都是基于AQS的。
AQS我在面試題中也見過他的身影,但一直不知道是什么東西。所以本篇我就來講講AQS這個玩意吧,至少知道它的概念是什么,對吧~
那么接下來我們就開始吧~
一、AQS是什么?首先我們來普及一下juc是什么:juc其實就是包的縮寫(java.util.concurrnt)
不要被人家唬到了,以為juc是什么一個牛逼的東西。其實指的是包而已~
我們可以發(fā)現(xiàn)lock包下有三個抽象的類:
AbstractOwnableSynchronizer
AbstractQueuedLongSynchronizer
AbstractQueuedSynchronizer
通常地:AbstractQueuedSynchronizer簡稱為AQS
我們Lock之類的兩個常見的鎖都是基于它來實現(xiàn)的:
那么我們來看看AbstractQueuedSynchronizer到底是什么,看一個類是干什么的最快途徑就是看它的頂部注釋
通讀了一遍,可以總結(jié)出以下比較關鍵的信息:
AQS其實就是一個可以給我們實現(xiàn)鎖的框架
內(nèi)部實現(xiàn)的關鍵是:先進先出的隊列、state狀態(tài)
定義了內(nèi)部類ConditionObject
擁有兩種線程模式
獨占模式
共享模式
在LOCK包中的相關鎖(常用的有ReentrantLock、 ReadWriteLock)都是基于AQS來構(gòu)建
一般我們叫AQS為同步器
二、簡單看看AQS上面也提到了AQS里邊最重要的是狀態(tài)和隊列,我們接下來就看看其源碼是怎么樣的...
2.1同步狀態(tài)使用volatile修飾實現(xiàn)線程可見性:
修改state狀態(tài)值時使用CAS算法來實現(xiàn):
2.2先進先出隊列這個隊列被稱為:CLH隊列(三個名字組成),是一個雙向隊列
看看它隊列源碼的組成:
static final class Node { // 共享 static final Node SHARED = new Node(); // 獨占 static final Node EXCLUSIVE = null; // 線程被取消了 static final int CANCELLED = 1; // 后繼線程需要喚醒 static final int SIGNAL = -1; // 等待condition喚醒 static final int CONDITION = -2; // 共享式同步狀態(tài)獲取將會無條件地傳播下去(沒看懂) static final int PROPAGATE = -3; // 初始為0,狀態(tài)是上面的幾種 volatile int waitStatus; // 前置節(jié)點 volatile Node prev; // 后繼節(jié)點 volatile Node next; volatile Thread thread; Node nextWaiter; final boolean isShared() { return nextWaiter == SHARED; } final Node predecessor() throws NullPointerException { Node p = prev; if (p == null) throw new NullPointerException(); else return p; } Node() { // Used to establish initial head or SHARED marker } Node(Thread thread, Node mode) { // Used by addWaiter this.nextWaiter = mode; this.thread = thread; } Node(Thread thread, int waitStatus) { // Used by Condition this.waitStatus = waitStatus; this.thread = thread; } }2.3acquire方法
獲取獨占鎖的過程就是在acquire定義的,該方法用到了模板設計模式,由子類實現(xiàn)的~
過程:acquire(int)嘗試獲取資源,如果獲取失敗,將線程插入等待隊列。插入等待隊列后,acquire(int)并沒有放棄獲取資源,而是根據(jù)前置節(jié)點狀態(tài)狀態(tài)判斷是否應該繼續(xù)獲取資源,如果前置節(jié)點是頭結(jié)點,繼續(xù)嘗試獲取資源,如果前置節(jié)點是SIGNAL狀態(tài),就中斷當前線程,否則繼續(xù)嘗試獲取資源。直到當前線程被park()或者獲取到資源,acquire(int)結(jié)束。
來源:
https://blog.csdn.net/panweiwei1994/article/details/78769703
2.4release方法釋放獨占鎖的過程就是在acquire定義的,該方法也用到了模板設計模式,由子類實現(xiàn)的~
過程:首先調(diào)用子類的tryRelease()方法釋放鎖,然后喚醒后繼節(jié)點,在喚醒的過程中,需要判斷后繼節(jié)點是否滿足情況,如果后繼節(jié)點不為且不是作廢狀態(tài),則喚醒這個后繼節(jié)點,否則從tail節(jié)點向前尋找合適的節(jié)點,如果找到,則喚醒.
來源:
https://zhuanlan.zhihu.com/p/27134110
三、最后總結(jié)一下AQS到底是什么吧:
juc包中很多可阻塞的類都是基于AQS構(gòu)建的
AQS可以說是一個給予實現(xiàn)同步鎖、同步器的一個框架,很多實現(xiàn)類都在它的的基礎上構(gòu)建的
在AQS中實現(xiàn)了對等待隊列的默認實現(xiàn),子類只要重寫部分的代碼即可實現(xiàn)(大量用到了模板代碼)
有興趣的同學可去看源碼和下面的鏈接繼續(xù)學習,我這里就不講述了。簡簡單單把AQS過一遍~
明天就看Lock顯式鎖實現(xiàn)咯~~~
參考資料:
https://blog.csdn.net/panweiwei1994/article/details/78769703
https://zhuanlan.zhihu.com/p/27134110
http://cmsblogs.com/?page_id=111
如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:Java3y。為了大家方便,剛新建了一下qq群:742919422,大家也可以去交流交流。謝謝支持了!希望能多介紹給其他有需要的朋友
文章的目錄導航:
https://zhongfucheng.bitcron.com/post/shou-ji/wen-zhang-dao-hang
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/69219.html
摘要:前言回顧前面多線程三分鐘就可以入個門了源碼剖析多線程基礎必要知識點看了學習多線程事半功倍鎖機制了解一下簡簡單單過一遍只有光頭才能變強上一篇已經(jīng)將鎖的基礎簡單地過了一遍了,因此本篇主要是講解鎖主要的兩個子類那么接下來我們就開始吧一鎖首先我們來 前言 回顧前面: 多線程三分鐘就可以入個門了! Thread源碼剖析 多線程基礎必要知識點!看了學習多線程事半功倍 Java鎖機制了解一下 AQ...
摘要:所以說我們的線程最好是交由線程池來管理,這樣可以減少對線程生命周期的管理,一定程度上提高性能。線程池不接收新任務,不處理已添加的任務,并且會中斷正在處理的任務。當所有的任務已終止,記錄的任務數(shù)量為,線程池會變?yōu)闋顟B(tài)。線程池徹底終止的狀態(tài)。 前言 只有光頭才能變強 回顧前面: ThreadLocal就是這么簡單 多線程三分鐘就可以入個門了! 多線程基礎必要知識點!看了學習多線程事半功倍...
摘要:此時線程需要鎖才能繼續(xù)往下執(zhí)行。但是線程的鎖并沒有釋放,線程的鎖也沒有釋放。 前言 只有光頭才能變強 回顧前面: ThreadLocal就是這么簡單 多線程三分鐘就可以入個門了! 多線程基礎必要知識點!看了學習多線程事半功倍 Java鎖機制了解一下 AQS簡簡單單過一遍 Lock鎖子類了解一下 線程池你真不來了解一下嗎? 本篇主要是講解死鎖,這是我在多線程的最后一篇了。主要將多線程...
摘要:無論在中出現(xiàn)什么,都可以認為它是對象除了八大基本數(shù)據(jù)類型。讓當前線程等待某個對象的鎖,當然應該通過這個對象來操作了。但是要注意的是方法調(diào)用后,被喚醒的線程不會立馬獲得到鎖對象。主要的區(qū)別在于在釋放同時,釋放了對象鎖的控制。 前言 五一回家又斷更了一個放假時間了~~~ 只有光頭才能變強 回顧前面: ThreadLocal就是這么簡單 多線程三分鐘就可以入個門了! 多線程基礎必要知識點!...
摘要:我們知道,這個函數(shù)將返回當前正在執(zhí)行的線程的中斷狀態(tài),并清除它。注意,中斷對線程來說只是一個建議,一個線程被中斷只是其中斷狀態(tài)被設為線程可以選擇忽略這個中斷,中斷一個線程并不會影響線程的執(zhí)行。 前言 系列文章目錄 上一篇文章 我們逐行分析了獨占鎖的獲取操作, 本篇文章我們來看看獨占鎖的釋放。如果前面的鎖的獲取流程你已經(jīng)趟過一遍了, 那鎖的釋放部分就很簡單了, 這篇文章我們直接開始看...
閱讀 2815·2023-04-25 14:41
閱讀 2426·2021-11-23 09:51
閱讀 3716·2021-11-17 17:08
閱讀 1702·2021-10-18 13:31
閱讀 5600·2021-09-22 15:27
閱讀 940·2019-08-30 15:54
閱讀 2254·2019-08-30 13:16
閱讀 760·2019-08-29 17:04