自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

最全Java鎖詳解:獨(dú)享鎖/共享鎖+公平鎖/非公平鎖+樂(lè)觀鎖/悲觀鎖

開(kāi)發(fā) 后端
CAS全稱(chēng) Compare And Swap(比較與交換),是一種無(wú)鎖算法。在不使用鎖(沒(méi)有線程被阻塞)的情況下實(shí)現(xiàn)多線程之間的變量同步。java.util.concurrent包中的原子類(lèi)就是通過(guò)CAS來(lái)實(shí)現(xiàn)了樂(lè)觀鎖。

[[254702]]

在Java并發(fā)場(chǎng)景中,會(huì)涉及到各種各樣的鎖如公平鎖,樂(lè)觀鎖,悲觀鎖等等,這篇文章介紹各種鎖的分類(lèi):

  • 公平鎖/非公平鎖
  • 可重入鎖
  • 獨(dú)享鎖/共享鎖
  • 樂(lè)觀鎖/悲觀鎖
  • 分段鎖
  • 自旋鎖

 

01.樂(lè)觀鎖 vs 悲觀鎖

樂(lè)觀鎖與悲觀鎖是一種廣義上的概念,體現(xiàn)了看待線程同步的不同角度,在Java和數(shù)據(jù)庫(kù)中都有此概念對(duì)應(yīng)的實(shí)際應(yīng)用。

1.樂(lè)觀鎖

顧名思義,就是很樂(lè)觀,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人不會(huì)修改,所以不會(huì)上鎖,但是在更新的時(shí)候會(huì)判斷一下在此期間別人有沒(méi)有去更新這個(gè)數(shù)據(jù),可以使用版本號(hào)等機(jī)制。

樂(lè)觀鎖適用于多讀的應(yīng)用類(lèi)型,樂(lè)觀鎖在Java中是通過(guò)使用無(wú)鎖編程來(lái)實(shí)現(xiàn),最常采用的是CAS算法,Java原子類(lèi)中的遞增操作就通過(guò)CAS自旋實(shí)現(xiàn)的。

CAS全稱(chēng) Compare And Swap(比較與交換),是一種無(wú)鎖算法。在不使用鎖(沒(méi)有線程被阻塞)的情況下實(shí)現(xiàn)多線程之間的變量同步。java.util.concurrent包中的原子類(lèi)就是通過(guò)CAS來(lái)實(shí)現(xiàn)了樂(lè)觀鎖。

簡(jiǎn)單來(lái)說(shuō),CAS算法有3個(gè)三個(gè)操作數(shù):

  • 需要讀寫(xiě)的內(nèi)存值 V。
  • 進(jìn)行比較的值 A。
  • 要寫(xiě)入的新值 B。

當(dāng)且僅當(dāng)預(yù)期值A(chǔ)和內(nèi)存值V相同時(shí),將內(nèi)存值V修改為B,否則返回V。這是一種樂(lè)觀鎖的思路,它相信在它修改之前,沒(méi)有其它線程去修改它;而Synchronized是一種悲觀鎖,它認(rèn)為在它修改之前,一定會(huì)有其它線程去修改它,悲觀鎖效率很低。

2.悲觀鎖

總是假設(shè)最壞的情況,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改,所以每次在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖,這樣別人想拿這個(gè)數(shù)據(jù)就會(huì)阻塞直到它拿到鎖。

傳統(tǒng)的MySQL關(guān)系型數(shù)據(jù)庫(kù)里邊就用到了很多這種鎖機(jī)制,比如行鎖,表鎖等,讀鎖,寫(xiě)鎖等,都是在做操作之前先上鎖。詳情可以參考:阿里P8架構(gòu)師談:MySQL行鎖、表鎖、悲觀鎖、樂(lè)觀鎖的特點(diǎn)與應(yīng)用

再比如上面提到的Java的同步synchronized關(guān)鍵字的實(shí)現(xiàn)就是典型的悲觀鎖。

 

3.總之:

悲觀鎖適合寫(xiě)操作多的場(chǎng)景,先加鎖可以保證寫(xiě)操作時(shí)數(shù)據(jù)正確。

樂(lè)觀鎖適合讀操作多的場(chǎng)景,不加鎖的特點(diǎn)能夠使其讀操作的性能大幅提升。

02.公平鎖 vs 非公平鎖

1.公平鎖

就是很公平,在并發(fā)環(huán)境中,每個(gè)線程在獲取鎖時(shí)會(huì)先查看此鎖維護(hù)的等待隊(duì)列,如果為空,或者當(dāng)前線程是等待隊(duì)列的***個(gè),就占有鎖,否則就會(huì)加入到等待隊(duì)列中,以后會(huì)按照FIFO的規(guī)則從隊(duì)列中取到自己。

公平鎖的優(yōu)點(diǎn)是等待鎖的線程不會(huì)餓死。缺點(diǎn)是整體吞吐效率相對(duì)非公平鎖要低,等待隊(duì)列中除***個(gè)線程以外的所有線程都會(huì)阻塞,CPU喚醒阻塞線程的開(kāi)銷(xiāo)比非公平鎖大。

2.非公平鎖

上來(lái)就直接嘗試占有鎖,如果嘗試失敗,就再采用類(lèi)似公平鎖那種方式。

非公平鎖的優(yōu)點(diǎn)是可以減少喚起線程的開(kāi)銷(xiāo),整體的吞吐效率高,因?yàn)榫€程有幾率不阻塞直接獲得鎖,CPU不必喚醒所有線程。缺點(diǎn)是處于等待隊(duì)列中的線程可能會(huì)餓死,或者等很久才會(huì)獲得鎖。

 

3.典型應(yīng)用:

java jdk并發(fā)包中的ReentrantLock可以指定構(gòu)造函數(shù)的boolean類(lèi)型來(lái)創(chuàng)建公平鎖和非公平鎖(默認(rèn)),比如:公平鎖可以使用new ReentrantLock(true)實(shí)現(xiàn)。

03.獨(dú)享所 vs 共享鎖

1.獨(dú)享鎖

是指該鎖一次只能被一個(gè)線程所持有。

2.共享鎖

是指該鎖可被多個(gè)線程所持有。

3.比較

對(duì)于Java ReentrantLock而言,其是獨(dú)享鎖。但是對(duì)于Lock的另一個(gè)實(shí)現(xiàn)類(lèi)ReadWriteLock,其讀鎖是共享鎖,其寫(xiě)鎖是獨(dú)享鎖。

讀鎖的共享鎖可保證并發(fā)讀是非常高效的,讀寫(xiě),寫(xiě)讀 ,寫(xiě)寫(xiě)的過(guò)程是互斥的。

獨(dú)享鎖與共享鎖也是通過(guò)AQS來(lái)實(shí)現(xiàn)的,通過(guò)實(shí)現(xiàn)不同的方法,來(lái)實(shí)現(xiàn)獨(dú)享或者共享。

4.AQS

抽象隊(duì)列同步器(AbstractQueuedSynchronizer,簡(jiǎn)稱(chēng)AQS)是用來(lái)構(gòu)建鎖或者其他同步組件的基礎(chǔ)框架,它使用一個(gè)整型的volatile變量(命名為state)來(lái)維護(hù)同步狀態(tài),通過(guò)內(nèi)置的FIFO隊(duì)列來(lái)完成資源獲取線程的排隊(duì)工作。

 

concurrent包的實(shí)現(xiàn)結(jié)構(gòu)如上圖所示,AQS、非阻塞數(shù)據(jù)結(jié)構(gòu)和原子變量類(lèi)等基礎(chǔ)類(lèi)都是基于volatile變量的讀/寫(xiě)和CAS實(shí)現(xiàn),而像Lock、同步器、阻塞隊(duì)列、Executor和并發(fā)容器等高層類(lèi)又是基于基礎(chǔ)類(lèi)實(shí)現(xiàn)。

04.分段鎖

分段鎖其實(shí)是一種鎖的設(shè)計(jì),并不是具體的一種鎖,對(duì)于ConcurrentHashMap而言,其并發(fā)的實(shí)現(xiàn)就是通過(guò)分段鎖的形式來(lái)實(shí)現(xiàn)高效的并發(fā)操作。

我們以ConcurrentHashMap來(lái)說(shuō)一下分段鎖的含義以及設(shè)計(jì)思想,ConcurrentHashMap中的分段鎖稱(chēng)為Segment,它即類(lèi)似于HashMap(JDK7與JDK8中HashMap的實(shí)現(xiàn))的結(jié)構(gòu),即內(nèi)部擁有一個(gè)Entry數(shù)組,數(shù)組中的每個(gè)元素又是一個(gè)鏈表;同時(shí)又是一個(gè)ReentrantLock(Segment繼承了ReentrantLock)。

當(dāng)需要put元素的時(shí)候,并不是對(duì)整個(gè)hashmap進(jìn)行加鎖,而是先通過(guò)hashcode來(lái)知道他要放在那一個(gè)分段中,然后對(duì)這個(gè)分段進(jìn)行加鎖,所以當(dāng)多線程put的時(shí)候,只要不是放在一個(gè)分段中,就實(shí)現(xiàn)了真正的并行的插入。

但是,在統(tǒng)計(jì)size的時(shí)候,可就是獲取hashmap全局信息的時(shí)候,就需要獲取所有的分段鎖才能統(tǒng)計(jì)。

分段鎖的設(shè)計(jì)目的是細(xì)化鎖的粒度,當(dāng)操作不需要更新整個(gè)數(shù)組的時(shí)候,就僅僅針對(duì)數(shù)組中的一項(xiàng)進(jìn)行加鎖操作。

責(zé)任編輯:武曉燕 來(lái)源: 優(yōu)知學(xué)院
相關(guān)推薦

2022-12-26 00:00:04

公平鎖非公平鎖

2024-01-29 01:08:01

悲觀鎖遞歸鎖讀寫(xiě)鎖

2022-07-12 08:56:18

公平鎖非公平鎖Java

2024-12-03 00:35:20

2019-11-28 16:00:06

重入鎖讀寫(xiě)鎖樂(lè)觀鎖

2022-05-09 07:37:04

Java非公平鎖公平鎖

2024-05-17 09:33:22

樂(lè)觀鎖CASversion

2018-07-31 10:10:06

MySQLInnoDB死鎖

2023-10-07 08:17:40

公平鎖非公平鎖

2018-07-31 15:05:51

Java公平鎖線程

2024-09-03 15:14:42

2025-04-23 08:45:00

悲觀鎖樂(lè)觀鎖并發(fā)控制機(jī)制

2020-08-24 08:13:25

非公平鎖源碼

2023-02-23 10:32:52

樂(lè)觀鎖

2011-08-18 13:44:42

Oracle悲觀鎖樂(lè)觀鎖

2020-09-16 07:56:28

多線程讀寫(xiě)鎖悲觀鎖

2009-09-25 16:43:44

Hibernate悲觀Hibernate樂(lè)觀

2021-03-30 09:45:11

悲觀鎖樂(lè)觀鎖Optimistic

2020-07-06 08:03:32

Java悲觀鎖樂(lè)觀鎖

2021-07-02 08:51:09

Redisson分布式鎖公平鎖
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)