synchronzied是一個重量級鎖
概念:什么叫重量級鎖?
就是申請資源必須經過kernel(內核也叫操作系統),調用。
(里面涉及到了用戶態(用戶空間)和內核態(os)的交互)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
輕量級鎖:是不經過操作系統。
cas:樂觀鎖(compare and swap)比較與交換(可以翻看Atomic原子類里源碼)
cas中的問題ABA
雖然,cas回成功但是也會帶來一些隱患(如下連接)
https://blog.csdn.net/aigoogle/article/details/38533047
解決方法怎么
在給對象加時間戳,版本號等都可以操作
原子類
在c++的代碼里,有一條匯編語言支持cas
但是,這條cmpchg1不具有原子性,點進lock_if_mp(%4)里
最終實現是lock cmpxchg 指令:表示在硬件在執行后面的指令會鎖定一個北橋總線。(相當於鎖定總線,但是比鎖總線要輕量級)解決了下面的問題
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
java對象在內存中的布局(導入工具:jol=java object layout)java對象布局
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.9</version>
</dependency>
我們可以理解為對象存放在堆里是一塊一塊的,每一塊都有布局:如圖
所謂的對象上鎖就是鎖對象的頭,所謂的鎖升級就是了解markword的變化
jdk團隊統計在jdk類庫里一些方法的提供synchronized的方法,大部分情況下對是在一個線程里運行,如果一直是重量級鎖會消耗大量資源提出優化
偏向鎖:(jvm默認打開並在jvm啟動后4秒啟動)如stringbuffer里面的大部分方法是安全的,如果在同一個線程里運行,就會出現上面的情況,那么jdk做法是當一個線程第一的到這把鎖,我們就認為這個鎖偏向於它,實際的做法是把線程的放到了對象的對象頭里。(偏向鎖到輕量級只要由競爭就之間升級)
偏向鎖為什么默認在jvm啟動后4秒才啟動,因為,當jvm剛運行的時候,里面有很多syn的方法,如果還是由偏向鎖再到自旋鎖,這樣會消耗大量資源。所以jvm既然知道是多線程,所以直接跳過了偏向鎖,轉變為自旋鎖。
讓jvm延遲4秒啟動,觀察markword
自旋鎖:(支持鎖鎖重入)假如有兩個線程同時,搶一把鎖,這個時候,誰第一個搶到,就把它的id放在對象的markword上。這個過程是while(操作)
重量級鎖:當線程競爭激烈,比如有10000個線程。這個時候如果還是自旋的話,會消耗大量的cpu,所以這個時候需要升級成重量級鎖。
重量級鎖和輕量級鎖,最大的區別是,重量級需要經過os(操作系統),並且它還是提供隊列,其中(waitset)存放等待的隊列,讓它們在里面排隊,(entrylist)存放競爭的隊列
(什么時候輕量級會升級到重量級呢)
jdk1.6之前是自旋超過10次,或者等待線程超過cpu核數的2分之一,自動升級
jdk1.6以后是jdk出來自適應自旋,它會自己判斷什么時候升級。