鎖,Synchronized,volatile

鎖,Synchronized,volatile

前言
配合上篇Java內存模型(JMM)一起看效果更好。本來想寫在一篇了。但是太長了。想想還是分開
理解了 Java內存模型,這個其實比較簡單

鎖 volatile synchronized

1. volatile

JMM內存模型
還是這張圖:volatile變量的寫相當於立即把更改的數據更新到主內存,讀相當於將本地內存總的地址置爲無效,每次從主內存中讀取

內存語義的實現:屏蔽重排序(具體的做法咱也不記得了)

volatile變量具有原子性(簡單操作是原子性,複雜操作就不是原子性)
happens-before的體現,前一個線程結果對後一個線程可見

2. 鎖

2.1 鎖是什麼

控制多個操作訪問共享資源的一種方式。目的就是避免多個線程同時操作一個資源,導致結果不可控。
內存語義:釋放鎖時將變量的更改刷新到內存(volatile寫類似);獲取鎖時將本地內存地址置爲無效(volatile讀類型)

2.2 Synchronized 虛擬機實現的鎖

synchronized是有虛擬機實現的鎖。每個對象都有一個monitor鎖
通過monitorenter和monitorexit 加鎖和釋放鎖
可以①對方法加鎖(鎖實例對象)②對靜態方法加鎖(鎖類對象,class對象)③對代碼塊加鎖(鎖代碼裏的對象)
synchronized優化後(1.6優化的?)引入了偏向鎖,輕量鎖。之前都是重量級鎖(加鎖和釋放鎖比較吃資源,需要阻塞線程)
偏向鎖:在對象頭裏存儲了線程的ID,獲取鎖前判斷是否是該線程,是這獲取到鎖。適用於沒有競爭的情況
輕量鎖:如果上面的線程獲取鎖的時候發現對象頭裏面的額線程ID不是自己(你心裏居然有了別人)。就升級爲輕量鎖。等待幾次CAS自旋後獲取鎖。適用於競爭小的情況下
重量級鎖:上面的輕量量級鎖發現CAS自旋了幾次還是無法獲取到鎖,這個時候就升級爲重量級鎖。就是普通的synchronized鎖了。會阻塞線程
上面的過程就是鎖升級。鎖無法降級

2.3 Java代碼實現的鎖

CAS compare and swap 比較並交換。如值時預期的數據,更換成我給的數據。Java通過這種方式來實現原子操作。Redis也是這種方式。其實比較常見

volatile 上面介紹的。
Java代碼實現的鎖核心就是這兩種方式

強調:不是說Java代碼實現的鎖效率更高,只是更靈活罷了
AQS AbstractQueuedSynchronizer 抽象隊列同步器,一般就叫同步器。一般面試就這個問得比較多 包含:鎖狀態,存放線程的隊列
ReentrantLock是面向鎖的使用者。AQS這是面向鎖的實現者。例如ReentrantLock就是利用AQS實現。內部類繼承AQS 。AQS屏蔽了鎖實現的細節。具體的不記得了,在IDEA裏面通過ctrl B 可以看到直接追溯到源碼看

Java代碼實現的鎖:
ReentrantLock(可重入鎖)
ReentrantReadWriteLock(讀寫鎖,讀鎖共享,寫鎖獨佔):看名字也知道,讀的優先級比寫高一點(在同一個線程下。如果再寫操作,其讀操作可以預讀,就是寫鎖還沒釋放,讀鎖先獲取到了,在釋放寫鎖。預寫是不行的。預讀是有條件的:在同一個線程下)

3. 小結

  • volatile就是JMM裏面可見性,或者說happens-before的體現。其實就是將馬上更新主內存,而且這個值每次獲取都是從主內存獲取
  • volatile 實際上用的很少的(當然在線程池裏面很常見。但是都是人家封裝好的,我們不用太費心)
  • synchronized是sun公司親兒子,經過優化後有偏向鎖,輕量鎖,重量級鎖,並不全是重量輕鎖,一般用這個就足夠了。
  • Java實現的鎖:ReentrantLock,ReentrantWriteReadLock這個和synchronized的區別在於哪了。有沒有聽說過一句話:“高玩用自定義模式,普通玩家用默認模式”。Java實現的鎖就是哪個自定義模式。有synchronize的功能,同時也有自己特有的功能:超時獲取,非阻塞式獲取,能夠被中斷獲取。有條件的獲取和釋放鎖
  • Java實現的鎖—AQS—volatile和CAS 慢慢深入的

先這樣吧
總目錄:Java進階之路-目錄

                空山新雨後,天氣晚來秋,明月鬆間照,清泉石上流
                《山居秋暝》 王維
                博主:五更依舊朝花落
                首次發佈時間:2020年5月8日21:22:54
                末次更新時間:
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章