天天看點

死磕 java同步系列之開篇

同步系列,這是彤哥想了好久的名字,本來是準備寫鎖相關的内容,但是java中的CountDownLatch、Semaphore、CyclicBarrier這些類又不屬于鎖,它們和鎖又有很多共同點,都是為了協同多線程的執行,都是一種同步器,是以這裡就借用同步來取名字了,也就是“同步系列”的來源。

這一篇的内容會比較多,大緻包含三大主題:java中的鎖、同步器、分布式鎖,大緻講的内容如下:

(1)volatile

(2)synchronized

(3)AQS及Condition

(4)ReentrantLock

(5)ReentrantReadWriteLock

(6)StampedLock

(7)CountDownLatch

(8)Semaphore

(9)CyclicBarrier

(10)Phaser

(11)Mysql實作分布式鎖

(12)Redis實作分布式鎖

(13)Zookeeper實作分布鎖

這些内容都比較晦澀難懂,網上也有比較多的資料,但往往講得不夠透徹,彤哥會盡量用通俗易懂的語言把這些問題講清楚。

關于鎖的名詞也有很多,彤哥大緻整理了下,全部列到這裡:

(1)公平鎖/非公平鎖

公平鎖,是指按照線程申請的順序擷取鎖。

非公平鎖,是指不是按照線程申請的順序擷取鎖,有可能後申請的線程反而先擷取到鎖,假如先來的線程一直擷取不到鎖,會造成鎖饑餓現象。

ReentrantLock中可以通過構造方法指定是否為公平鎖,預設為非公平鎖,非公平鎖的優點在于吞吐量大。

synchronized無法指定為公平鎖,一直都是非公平鎖。

(2)可重入鎖

可重入鎖,是指一個線程擷取鎖之後再嘗試擷取鎖時會自動擷取鎖,可重入鎖的優點是避免死鎖。

ReentrantLock和synchronized都是可重入鎖。

(3)獨享鎖/共享鎖

獨享鎖,是指鎖一次隻能被一個線程持有。

共享鎖,是指鎖一次可以被多個線程持有。

ReentrantLock和synchronized都是獨享鎖,ReadWriteLock的讀鎖是共享鎖,寫鎖是獨享鎖。

(4)互斥鎖/讀寫鎖

與獨享鎖/共享鎖的概念差不多,是獨享鎖/共享鎖的具體實作。

ReentrantLock和synchronized都是互斥鎖

ReadWriteLock是讀寫鎖

(5)樂觀鎖/悲觀鎖

悲觀鎖,是指認為對于同一個資料的并發操作必然會發生修改,即使不會發生修改也這麼認為,是以一定要加鎖。

樂觀鎖,是指認為對于同一個資料的并發操作不一定會發生修改,在更新資料的時候,嘗試去更新資料,如果失敗就不斷嘗試。

悲觀鎖适用于寫操作多的場景,樂觀鎖适用于讀操作多的場景。

(6)分段鎖

分段鎖,是一種鎖的設計思路,它細化了鎖的粒度,主要運用在ConcurrentHashMap中,實作高效的并發操作,當操作不需要更新整個數組時,就隻鎖數組中的一項就可以了。

(7)偏向鎖/輕量級鎖/重量級鎖

這三個鎖主要是針對synchronized進行優化使用的,主要是通過對象螢幕在對象頭中的字段來表明的。

偏向鎖,是指一段同步代碼一直被一個線程通路,那麼這個線程會自動擷取鎖,降低擷取鎖的代價。

輕量級鎖,是指當鎖是偏向鎖時,被另一個線程所通路,偏向鎖會更新為輕量級鎖,這個線程會通過自旋的方式嘗試擷取鎖,不會阻塞,提高性能。

重量級鎖,是指當鎖是輕量級鎖時,當自旋的線程自旋了一定的次數後,還沒有擷取到鎖,就會進入阻塞狀态,該鎖更新為重量級鎖,重量級鎖會使其他線程阻塞,性能降低。

(8)自旋鎖

自旋鎖,是指嘗試擷取鎖的線程不會阻塞,而是循環的方式不斷嘗試,這樣的好處是減少線程的上下文切換帶來的開鎖,提高性能,缺點是循環會消耗CPU。

(9)螢幕鎖

synchronized的實作方式,使用monitorenter和monitorexit來實作。

(10)mutex鎖

互斥鎖,LockSupport.part()底層是通過mutex實作的。

招募令:

因為彤哥本身工作也比較繁忙,很難做到日更,是以這裡誠邀廣大好友積極投稿,大家一起學習一起進步。

可在公衆号背景給我留言“投稿”,互加好友詳細讨論投稿内容。

當然,其它問題也可在公衆号背景留言,不管是生活上、工作上、心理上還是身體上的,歡迎叨擾,留言必回。

歡迎關注我的公衆号“彤哥讀源碼”,檢視更多源碼系列文章, 與彤哥一起暢遊源碼的海洋。