在Java并發(fā)場景中有哪些鎖

這篇文章主要介紹了在Java并發(fā)場景中有哪些鎖,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

成都做網(wǎng)站、網(wǎng)站建設(shè)的開發(fā),更需要了解用戶,從用戶角度來建設(shè)網(wǎng)站,獲得較好的用戶體驗。創(chuàng)新互聯(lián)公司多年互聯(lián)網(wǎng)經(jīng)驗,見的多,溝通容易、能幫助客戶提出的運營建議。作為成都一家網(wǎng)絡(luò)公司,打造的就是網(wǎng)站建設(shè)產(chǎn)品直銷的概念。選擇創(chuàng)新互聯(lián)公司,不只是建站,我們把建站作為產(chǎn)品,不斷的更新、完善,讓每位來訪用戶感受到浩方產(chǎn)品的價值服務(wù)。

01.樂觀鎖 vs 悲觀鎖

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

1.樂觀鎖

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

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

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

簡單來說,CAS算法有3個三個操作數(shù):

  • 需要讀寫的內(nèi)存值 V。

  • 進行比較的值 A。

  • 要寫入的新值 B。

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

2.悲觀鎖

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

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

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

在Java并發(fā)場景中有哪些鎖

3.總之:

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

樂觀鎖適合讀操作多的場景,不加鎖的特點能夠使其讀操作的性能大幅提升。

02.公平鎖 vs 非公平鎖

1.公平鎖

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

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

2.非公平鎖

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

非公平鎖的優(yōu)點是可以減少喚起線程的開銷,整體的吞吐效率高,因為線程有幾率不阻塞直接獲得鎖,CPU不必喚醒所有線程。缺點是處于等待隊列中的線程可能會餓死,或者等很久才會獲得鎖。

在Java并發(fā)場景中有哪些鎖

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

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

03.獨享所 vs 共享鎖

1.獨享鎖

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

2.共享鎖

是指該鎖可被多個線程所持有。

3.比較

對于Java  ReentrantLock而言,其是獨享鎖。但是對于Lock的另一個實現(xiàn)類ReadWriteLock,其讀鎖是共享鎖,其寫鎖是獨享鎖。

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

獨享鎖與共享鎖也是通過AQS來實現(xiàn)的,通過實現(xiàn)不同的方法,來實現(xiàn)獨享或者共享。

4.AQS

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

在Java并發(fā)場景中有哪些鎖

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

04.分段鎖

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

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

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

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

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

感謝你能夠認真閱讀完這篇文章,希望小編分享的“在Java并發(fā)場景中有哪些鎖”這篇文章對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!

網(wǎng)頁標題:在Java并發(fā)場景中有哪些鎖
轉(zhuǎn)載來于:http://muchs.cn/article36/phocsg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計、電子商務(wù)、網(wǎng)站建設(shè)、全網(wǎng)營銷推廣定制開發(fā)網(wǎng)站改版

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)