JAVA多線程之Synchronize 關鍵字原理

image

眾所周知 Synchronize 關鍵字是解決并發問題常用解決方案,有以下三種使用方式:

  • 同步普通方法,鎖的是當前對象。
  • 同步靜態方法,鎖的是當前 Class 對象。
  • 同步塊,鎖的是 {} 中的對象。

實現原理:
JVM 是通過進入、退出對象監視器( Monitor )來實現對方法、同步塊的同步的。

具體實現是在編譯之后在同步方法調用前加入一個 monitor.enter 指令,在退出方法和異常處插入 monitor.exit 的指令。

其本質就是對一個對象監視器( Monitor )進行獲取,而這個獲取過程具有排他性從而達到了同一時刻只能一個線程訪問的目的。

而對于沒有獲取到鎖的線程將會阻塞到方法入口處,直到獲取鎖的線程 monitor.exit 之后才能嘗試繼續獲取鎖。

流程圖如下:

image

通過一段代碼來演示:

    public static void main(String[] args) { synchronized (Synchronize.class){ System.out.println("Synchronize"); } } 

使用 javap -c Synchronize 可以查看編譯之后的具體信息。

public class com.crossoverjie.synchronize.Synchronize { public com.crossoverjie.synchronize.Synchronize(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: ldc #2 // class com/crossoverjie/synchronize/Synchronize 2: dup 3: astore_1 **4: monitorenter** 5: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream; 8: ldc #4 // String Synchronize 10: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 13: aload_1 **14: monitorexit** 15: goto 23 18: astore_2 19: aload_1 20: monitorexit 21: aload_2 22: athrow 23: return Exception table: from to target type 5 15 18 any 18 21 18 any } 

可以看到在同步塊的入口和出口分別有 monitorenter,monitorexit
指令。

鎖優化

synchronize 很多都稱之為重量鎖,JDK1.6 中對 synchronize 進行了各種優化,為了能減少獲取和釋放鎖帶來的消耗引入了偏向鎖輕量鎖

輕量鎖

當代碼進入同步塊時,如果同步對象為無鎖狀態時,當前線程會在棧幀中創建一個鎖記錄(Lock Record)區域,同時將鎖對象的對象頭中 Mark Word 拷貝到鎖記錄中,再嘗試使用 CASMark Word 更新為指向鎖記錄的指針。

如果更新成功,當前線程就獲得了鎖。

如果更新失敗 JVM 會先檢查鎖對象的 Mark Word 是否指向當前線程的鎖記錄。

如果是則說明當前線程擁有鎖對象的鎖,可以直接進入同步塊。

不是則說明有其他線程搶占了鎖,如果存在多個線程同時競爭一把鎖,輕量鎖就會膨脹為重量鎖

解鎖

輕量鎖的解鎖過程也是利用 CAS 來實現的,會嘗試鎖記錄替換回鎖對象的 Mark Word 。如果替換成功則說明整個同步操作完成,失敗則說明有其他線程嘗試獲取鎖,這時就會喚醒被掛起的線程(此時已經膨脹為重量鎖)

輕量鎖能提升性能的原因是�:認為大多數鎖在整個同步周期都不存在競爭,所以使用 CAS 比使用互斥開銷更少。但如果鎖競爭激烈,輕量鎖就不但有互斥的開銷,還有 CAS 的開銷,甚至比重量鎖更慢。

偏向鎖

為了進一步的降低獲取鎖的代價,JDK1.6 之后還引入了偏向鎖。

偏向鎖的特征是:鎖不存在多線程競爭,并且應由一個線程多次獲得鎖。

當線程訪問同步塊時,會使用 CAS 將線程 ID 更新到鎖對象的 Mark Word 中,如果更新成功則獲得偏向鎖,并且之后每次進入這個對象鎖相關的同步塊時都不需要再次獲取鎖了。

釋放鎖

當有另外一個線程獲取這個鎖時,持有偏向鎖的線程就會釋放鎖,釋放時會等待全局安全點(這一時刻沒有字節碼運行),接著會暫停擁有偏向鎖的線程,根據鎖對象目前是否被鎖來判定將對象頭中的 Mark Word 設置為無鎖或者是輕量鎖狀態。

輕量鎖可以提高帶有同步卻沒有競爭的程序性能,但如果程序中大多數鎖都存在競爭時,那偏向鎖就起不到太大作用。可以使用 -XX:-userBiasedLocking=false 來關閉偏向鎖,并默認進入輕量鎖。

其他優化

適應性自旋

在使用 CAS 時,如果操作失敗,CAS 會自旋再次嘗試。由于自旋是需要消耗 CPU 資源的,所以如果長期自旋就白白浪費了 CPUJDK1.6加入了適應性自旋:

如果某個鎖自旋很少成功獲得,那么下一次就會減少自旋。

號外

最近在總結一些 Java 相關的知識點,感興趣的朋友可以一起維護。

地址: https://github.com/crossoverJie/Java-Interview



作者:crossoverJie
鏈接:https://www.jianshu.com/p/2ba154f275ea

轉載于:https://www.cnblogs.com/PrestonL/p/9507985.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/397150.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/397150.shtml
英文地址,請注明出處:http://en.pswp.cn/news/397150.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

iOS-數據持久化-第三方框架FMDB的使用

FMDB簡單介紹 一、簡單說明 1.什么是FMDB FMDB是iOS平臺的SQLite數據庫框架 FMDB以OC的方式封裝了SQLite的C語言API 2.FMDB的優點 使用起來更加面向對象&#xff0c;省去了很多麻煩、冗余的C語言代碼 對比蘋果自帶的Core Data框架&#xff0c;更加輕量級和靈活 提供了多線程安全…

電腦word文檔打不開怎么辦_word怎么轉pdf?兩個值得學習的高效轉換法

word怎么轉pdf&#xff1f;兩個值得學習的高效轉換法word怎么轉pdf&#xff1f;pdf格式是我們經常能夠使用到的格式&#xff0c;因為pdf格式在傳遞的過程中能更好地避免文件出現亂碼打不開或誤觸導致文件被修改的情況。那如果想要把word文件轉換成pdf格式以避免閱讀word時文件被…

sql server常用函數、常用語句

一、常用函數 1.字符串函數 &#xff1a; charindex(:,abc:123) --尋找一個字符在一段字符串中起始的位置 len(zhangsan) --獲取一段字符串的長度 left(Ly,君子之耀,2) --從一段字符串左邊返回指定長度的字符 right(char_expr,int_expr) --返回字符串右邊int_expr個字符 …

python 矩陣乘法 跳過nan_python – Numpy:當一些向量元素等于零時,矩陣向量乘法不會跳過計算嗎?...

我最近一直致力于一個項目,其中我的大部分時間花費在密集矩陣A和稀疏向量v上(見here).在我嘗試減少計算時,我注意到A.dot(v)的運行時間不受v的零條目數的影響.為了解釋為什么我希望在這種情況下改進運行時,讓result A.dot.v使得j 1的結果[j] sum_i(A [i,j] * v [j])… v.sha…

[轉]Responsive Tables Demo

本文轉自&#xff1a;http://elvery.net/demo/responsive-tables/ A quick and dirty look at some techniques for designing responsive table layouts. This was put together in haste (and with the aid of Twitter Bootstrap) for What Do You Know Brisbane hosted by W…

Scala函數式對象-有理數

有理數類的表示 實現規范&#xff1a;支持有理數的加減乘除&#xff0c;并支持有理數的規范表示 1.定義Rational 首先&#xff0c;考慮用戶如何使用這個類&#xff0c;我們已經決定使用“Immutable”方式來使用Rational對象&#xff0c;我們需要用戶在定義Rational對象時提供分…

2020雙十一實時大屏_2020拼多多雙十一,拼多多雙十一活動

2020拼多多雙十一&#xff0c;拼多多雙十一活動&#xff0c;2020拼多多雙十一&#xff0c;拼多多雙十一活動2020拼多多雙十一&#xff0c;拼多多雙十一活動拼多多雙11來了全球狂歡節先領券再購物低價風暴 震撼來襲沒有最低 只有更低拼多多優惠券商城拼多多優惠商城&#xff0c;…

dataTables本地刷新數據解決只能初始化一次問題

2019獨角獸企業重金招聘Python工程師標準>>> dataTables的表格只能初始化一次&#xff0c;這樣如果需要動態改變表格數據的話就需要寫多個表格&#xff0c;這樣很顯然不是一個好的解決方案。 dataTables Api提供了刷新數據解決方案&#xff1a; 這里大概說一下案例&…

安裝Ubuntu版本linux過程中沒有提示設置root用戶密碼問題的解決辦法

原來ubunto不提倡設置root用戶&#xff0c;系統安裝成功后&#xff0c;root密碼是隨機的&#xff0c;那么在這種情況下如何得到root權限吶&#xff0c;具體方法如下&#xff1a; 終端中輸入&#xff1a;sudo passwd root 此時重新設置原登錄用戶的密碼。 設置成功后在終端繼續輸…

linux命令headtail

一、head語法head [-n -k ]... [FILE]...//k是數字默認是顯示開頭前10行。head /etc/passwd顯示開頭前5行head -5 /etc/passwdhead -n 5 /etc/passwd&#xff08;注意和以下的有-的差別&#xff09;head -n 5 /etc/passwd 除最后k行外&#xff0c;顯示剩余所有內容。head -n -5…

用-force –opengl 指令_蘋果新系統ios14新功能匯總 輕點背面等小技巧怎么用

在 iOS 14 以及更新系統中&#xff0c;蘋果為 iPhone X 以及更新機型帶來了“輕點背面”功能&#xff0c;可以讓用戶輕點手機背面來實現更多操作&#xff0c;并且這項功能還支持“快捷指令”。例如&#xff0c;如果您不希望應用讀取剪貼板中私密內容&#xff0c;可以利用“輕點…

PE文件格式(加密與解密3)(一)

本次的了解主要講解 PE的基本概念、MS-DOS文件頭、PE文件頭、區塊、輸入表、輸出表等。 這里我將會結合一個簡單的小程序來加深我對PE文件結構的了解。 使用學習工具&#xff1a;有StudyPE、LordPE、PEID。 學習PE建議看書。。和自己動手。。。 PE文件&#xff1a; 在WIN上&…

mysql用戶_MySQL用戶權限管理詳解

用戶權限管理主要有以下作用&#xff1a;1. 可以限制用戶訪問哪些庫、哪些表2. 可以限制用戶對哪些表執行SELECT、CREATE、DELETE、DELETE、ALTER等操作3. 可以限制用戶登錄的IP或域名4. 可以限制用戶自己的權限是否可以授權給別的用戶一、用戶授權mysql> grant all privile…

對ContentProvider中getType方法的一點理解

在上篇博客中我們介紹了自定義ContentProvider&#xff0c;但是遺漏掉了一個方法&#xff0c;那就是getType&#xff0c;自定義ContentProvider一般用不上getType方法&#xff0c;但我們還是一起來探究下這個方法究竟是干什么的&#xff1f;我們先來看看ContentProvider中對這個…

手把手教Electron+vue的使用

.現如今前端框架數不勝數&#xff0c;尤其是angular、vue吸引一大批前端開發者&#xff0c;在這個高新技術快速崛起的時代&#xff0c;自然少不了各種框架的結合使用。接下來是介紹electronvue的結合使用。 2.Electron是什么&#xff1f;&#xff1f; 對于我來說Electron相當于…

shell循環和分支

循環和分支對代碼塊的操作是構造組織shell腳本的關鍵. 循環和分支結構為腳本編程提供了操作代碼塊的工具.10.1. Loops循環就是重復一些命令的代碼塊,如果條件不滿足就退出循環.for loopsfor arg in [list]這是一個基本的循環結構.它與C的for結構有很大不同.forarg in [list]do …

mysql主從_MySQL主從原理及配置詳解

MySQL主從配置及原理&#xff0c;供大家參考&#xff0c;具體內容如下一、環境選擇&#xff1a;1.Centos 6.52.MySQL 5.7二、什么是MySQL主從復制MySQL主從復制是其最重要的功能之一。主從復制是指一臺服務器充當主數據庫服務器&#xff0c;另一臺或多臺服務器充當從數據庫服務…

引導修復 不是活動的_河南省視頻數據修復中心

河南省視頻數據修復中心 lk6afds河南省視頻數據修復中心 文件預覽我找到了我要恢復文件&#xff0c;可是&#xff0c;這個文件能能正確恢復呢。沒有用的文件不可以刪掉嗎。我們先來看看盤文件夾都是什么吧。(以下僅限于~系統)一般來說&#xff0c;剛剛安裝的電腦系統盤主要包含…

企業日志分析 五大問題需重點注意

資訊 | 安全 | 論壇 | 下載 | 讀書 | 程序開發 | 數據庫 | 系統 | 網絡 | 電子書 | 微信學院 | 站長學院 | 源碼 | QQ | 專欄 | 考試 | 系統安全| 網站安全| 企業安全| 網絡安全| 工具軟件| 殺毒防毒| 加密解密|首頁 > 安全 > 企業安全 > 正文企業安全…

sqlite換成mysql_從SQLITE的數據轉到MYSQL

接同事需求&#xff0c;要求從SQLITE的數據轉到MYSQL&#xff0c;這東西以前也沒接觸過。這里搜搜&#xff0c;那里試試&#xff0c;下面把過程列一下。主要過程分三步&#xff1a;1&#xff0c;把SQLITE表結構導出來&#xff0c;作一定的格式調整2&#xff0c;把SQLITE數據導出…