欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

帶你快速搞定java多線程(4)

 更新時(shí)間:2021年07月14日 17:01:33   作者:香菜聊游戲  
這篇文章主要介紹了java多線程編程實(shí)例,分享了幾則多線程的實(shí)例代碼,具有一定參考價(jià)值,加深多線程編程的理解還是很有幫助的,需要的朋友可以參考下

1、AQS 是什么?

AQS 是類 AbstractQueuedSynchronizer的簡稱,也是常用鎖的基類,比如常見的ReentrantLock,Semaphore,CountDownLatch 等等。

AQS提供了一種實(shí)現(xiàn)阻塞鎖和一系列依賴FIFO等待隊(duì)列的同步器的框架。是Java提供的一種模板,一般在現(xiàn)有同步器無法完成的時(shí)候可以自行擴(kuò)展。當(dāng)然也可以自己實(shí)現(xiàn),不過既然有現(xiàn)成的為什么還要自己瞎雞兒寫。

圖片

2、AQS 模型

圖片

注意:圖來自網(wǎng)上,具體的原地點(diǎn)在哪我也不知道。如果有問題可以聯(lián)系我。

解釋:整個(gè)模型相當(dāng)于在食堂吃飯,只開了一個(gè)窗口,只有一個(gè)打飯的師傅(state),所有想要吃飯的線程必須排隊(duì)等待,直到輪到自己。

AQS就是基于隊(duì)列,用共享變量state,線程通過CAS去改變狀態(tài)符,成功則獲取鎖成功,失敗則進(jìn)入等待隊(duì)列,等待被喚醒。代碼解決現(xiàn)實(shí)問題,現(xiàn)實(shí)問題催生解決方案。

3、AQS state

state 代表 共享資源和一個(gè)FIFO線程等待隊(duì)列(多線程爭用資源被阻塞時(shí)會(huì)進(jìn)入此隊(duì)列)。

state的訪問方式有三種:

  • getState()
  • setState()
  • compareAndSetState()

4、AQS 兩種資源共享方式:

1.Exclusive:獨(dú)占,只有一個(gè)線程能執(zhí)行,如ReentrantLock

2.Share:共享,多個(gè)線程可以同時(shí)執(zhí)行,如Semaphore、CountDownLatch、ReadWriteLock,CyclicBarrier。

5、模板方式實(shí)現(xiàn)自定義

不同的自定義同步器爭用共享資源的方式也不同。自定義同步器在實(shí)現(xiàn)時(shí)只需要實(shí)現(xiàn)共享資源state的獲取與釋放方式即可,至于具體線程等待隊(duì)列的維護(hù)(如獲取資源失敗入隊(duì)/喚醒出隊(duì)等),AQS已經(jīng)在頂層實(shí)現(xiàn)好了。自定義時(shí)主要實(shí)現(xiàn)以下幾種方法:

  • isHeldExclusively():該線程是否正在獨(dú)占資源。只有用到condition才需要去實(shí)現(xiàn)它。
  • tryAcquire(int):獨(dú)占方式。嘗試獲取資源,成功則返回true,失敗則返回false。
  • tryRelease(int):獨(dú)占方式。嘗試釋放資源,成功則返回true,失敗則返回false。
  • tryAcquireShared(int):共享方式。嘗試獲取資源。負(fù)數(shù)表示失??;0表示成功,但沒有剩余可用資源;正數(shù)表示成功,且有剩余資源。
  • tryReleaseShared(int):共享方式。嘗試釋放資源,如果釋放后允許喚醒后續(xù)等待結(jié)點(diǎn)返回true,否則返回false。

以ReentrantLock為例,state初始化為0,表示未鎖定狀態(tài)。A線程lock()時(shí),會(huì)調(diào)用tryAcquire()獨(dú)占該鎖并將state+1。此后,其他線程再tryAcquire()時(shí)就會(huì)失敗,直到A線程unlock()到state=0(即釋放鎖)為止,其它線程才有機(jī)會(huì)獲取該鎖。當(dāng)然,釋放鎖之前,A線程自己是可以重復(fù)獲取此鎖的(state會(huì)累加),這就是可重入的概念。但要注意,獲取多少次就要釋放多么次,這樣才能保證state是能回到零態(tài)的。

再以CountDownLatch以例,任務(wù)分為N個(gè)子線程去執(zhí)行,state也初始化為N(注意N要與線程個(gè)數(shù)一致)。這N個(gè)子線程是并行執(zhí)行的,每個(gè)子線程執(zhí)行完后countDown()一次,state會(huì)CAS減1。等到所有子線程都執(zhí)行完后(即state=0),會(huì)unpark()主調(diào)用線程,然后主調(diào)用線程就會(huì)從await()函數(shù)返回,繼續(xù)后余動(dòng)作。

一般來說,自定義同步器要么是獨(dú)占方法,要么是共享方式,他們也只需實(shí)現(xiàn)tryAcquire-tryRelease、tryAcquireShared-tryReleaseShared中的一種即可。但AQS也支持自定義同步器同時(shí)實(shí)現(xiàn)獨(dú)占和共享兩種方式,如ReentrantReadWriteLock。

6、鎖的分類:公平鎖和非公平鎖,樂觀鎖和悲觀鎖

  • 公平鎖:當(dāng)線程A獲取訪問該對象,獲取到鎖后,此時(shí)內(nèi)部存在一個(gè)計(jì)數(shù)器num+1,其他線程想訪問該對象,就會(huì)進(jìn)行排隊(duì)等待(等待隊(duì)列最前一個(gè)線程處于待喚醒狀態(tài)),直到線程A釋放鎖(num = 0),此時(shí)會(huì)喚醒處于待喚醒狀態(tài)的線程進(jìn)行獲取鎖的操作,一直循環(huán)。如果線程A再次嘗試獲取該對象鎖時(shí),會(huì)檢查該對象鎖釋放已經(jīng)被占用,如果還是當(dāng)前線程占用鎖,則直接獲得鎖,不用進(jìn)入排隊(duì)。
  • 非公平鎖:當(dāng)線程A在釋放鎖后,等待對象的線程會(huì)進(jìn)行資源競爭,競爭成功的線程將獲取該鎖,其他線程繼續(xù)睡眠。

公平鎖是嚴(yán)格的以FIFO的方式進(jìn)行鎖的競爭,但是非公平鎖是無序的鎖競爭,剛釋放鎖的線程很大程度上能比較快的獲取到鎖,隊(duì)列中的線程只能等待,所以非公平鎖可能會(huì)有“饑餓”的問題。但是重復(fù)的鎖獲取能減小線程之間的切換,而公平鎖則是嚴(yán)格的線程切換,這樣對操作系統(tǒng)的影響是比較大的,所以非公平鎖的吞吐量是大于公平鎖的,這也是為什么JDK將非公平鎖作為默認(rèn)的實(shí)現(xiàn)。

  • 悲觀鎖:總是假設(shè)最壞的情況,每次想要使用數(shù)據(jù)的時(shí)候就恰好別人也要修改數(shù)據(jù),一切是以安全第一,所以在每次操作資源的時(shí)候都會(huì)先加鎖,不管有沒有人搶,然后獨(dú)占資源。Java中synchronized和ReentrantLock等獨(dú)占鎖就是悲觀鎖思想的實(shí)現(xiàn)
  • 樂觀鎖:樂觀鎖和悲觀鎖剛好相反,自己使用資源的時(shí)候沒有人搶,所以不需要上鎖。樂觀鎖的實(shí)現(xiàn)方案一般來說有兩種:版本號機(jī)制 和 CAS實(shí)現(xiàn) 。樂觀鎖多適用于多度的應(yīng)用類型,這樣可以提高吞吐量。

7、CAS

CAS(Compare And Swap),即比較并交換。是解決多線程并行情況下使用鎖造成性能損耗的一種機(jī)制,CAS操作包含三個(gè)操作數(shù)——內(nèi)存位置(V)、預(yù)期原值(A)和新值(B)。如果內(nèi)存位置的值與預(yù)期原值相匹配,那么處理器會(huì)自動(dòng)將該位置值更新為新值。否則,處理器不做任何操作。無論哪種情況,它都會(huì)在CAS指令之前返回該位置的值。CAS有效地說明了“我認(rèn)為位置V應(yīng)該包含值A(chǔ);如果包含該值,則將B放到這個(gè)位置;否則,不要更改該位置,只告訴我這個(gè)位置現(xiàn)在的值即可。sun.misc.Unsafe 類提供了硬件級別的原子操作來實(shí)現(xiàn)這個(gè)CAS。java.util.concurrent 包下的大量類都使用了這個(gè) Unsafe.java 類的CAS操作。Unsafe 包是C++的接口實(shí)現(xiàn),直接可以訪問計(jì)算機(jī)的內(nèi)存等敏感操作,所以標(biāo)記為Unsafe。

CAS 是直接調(diào)用計(jì)算機(jī)的硬件指令,是硬件級別的線程同步,也是一種樂觀鎖。

8、總結(jié)

從整體上說了下AQS,沒有深入到代碼層級,先理解思想,后看具體實(shí)現(xiàn)。你理解了嗎?下期具體分析一個(gè)CountDownLatch 源碼,從細(xì)節(jié)理解AQS。

本篇文章就到這里了,希望能對你有所幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • springboot攔截器過濾token,并返回結(jié)果及異常處理操作

    springboot攔截器過濾token,并返回結(jié)果及異常處理操作

    這篇文章主要介紹了springboot攔截器過濾token,并返回結(jié)果及異常處理操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • 詳解使用SSM實(shí)現(xiàn)簡單工作流系統(tǒng)之實(shí)現(xiàn)篇

    詳解使用SSM實(shí)現(xiàn)簡單工作流系統(tǒng)之實(shí)現(xiàn)篇

    這篇文章主要介紹了使用SSM實(shí)現(xiàn)簡單工作流系統(tǒng)之實(shí)現(xiàn)篇,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-12-12
  • SpringMVC空指針異常NullPointerException解決及原理解析

    SpringMVC空指針異常NullPointerException解決及原理解析

    這篇文章主要介紹了SpringMVC空指針異常NullPointerException解決及原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Java獲取鏈接上的參數(shù)三種方法舉例

    Java獲取鏈接上的參數(shù)三種方法舉例

    在Java中,我們經(jīng)常需要從URL鏈接中獲取參數(shù),下面這篇文章主要給大家介紹了關(guān)于Java如何獲取鏈接上參數(shù)的三種方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-06-06
  • idea快速搭建spring cloud注冊中心與注冊的方法

    idea快速搭建spring cloud注冊中心與注冊的方法

    這篇文章主要介紹了idea快速搭建spring cloud注冊中心與注冊的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-07-07
  • 解讀Java和JavaScript區(qū)別與聯(lián)系

    解讀Java和JavaScript區(qū)別與聯(lián)系

    這篇文章主要介紹了解讀Java和JavaScript區(qū)別與聯(lián)系,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • Java實(shí)現(xiàn)HTML轉(zhuǎn)為Word的示例代碼

    Java實(shí)現(xiàn)HTML轉(zhuǎn)為Word的示例代碼

    本文以Java代碼為例為大家詳細(xì)介紹如何實(shí)現(xiàn)將HTML文件轉(zhuǎn)為Word文檔(.docx、.doc)。在實(shí)際開發(fā)場景中可參考此方法來轉(zhuǎn)換,感興趣的可以了解一下
    2022-06-06
  • 聊聊mybatis sql的括號問題

    聊聊mybatis sql的括號問題

    這篇文章主要介紹了mybatis sql的括號問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java多線程下載網(wǎng)圖的完整案例

    Java多線程下載網(wǎng)圖的完整案例

    這篇文章主要給大家介紹了關(guān)于Java多線程下載網(wǎng)圖的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Spring Boot整合Spring Data Jpa代碼實(shí)例

    Spring Boot整合Spring Data Jpa代碼實(shí)例

    這篇文章主要介紹了Spring Boot整合Spring Data Jpa代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11

最新評論