溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java中Synchronized的原理是什么

發布時間:2021-06-17 17:20:49 來源:億速云 閱讀:272 作者:Leah 欄目:大數據

本篇文章為大家展示了Java中Synchronized的原理是什么,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

原本的問題

Synchronized是基于底層操作系統的 Mutex Lock 實現的,每次獲取鎖和釋放鎖的操作都會帶來用戶態內核態的切換,從而增加系統性能開銷。

因此,在鎖競爭激烈的情況下,Synchronized同步鎖在性能上就表現得非常糟糕,它也常被大家稱為重量級鎖。

到了 JDK1.5 版本,并發包中新增了 Lock 接口來實現鎖功能,它提供了與 Synchronized 關鍵字類似的同步功能,只是在使用時需要顯示獲取鎖和釋放鎖。

在單個線程重復申請鎖的情況下,JDK1.5 版本的 Lock 性能要比 Synchronized 鎖的性能好很多,也就是當時的 Synchronized 并不具備可重入鎖的功能。

那么當時的 Synchronized 是怎么實現的?又為什么不具備可重入的功能呢?

Synchronized原理

JVM 中的同步是基于進入和退出管程(Monitor)對象實現的。每個對象實例都會有一個 Monitor,Monitor 可以和對象一起創建、銷毀。

當多個線程同時訪問一段同步代碼時,多個線程會先被存放在EntryList集合(也可稱為阻塞隊列)中,處于BLOCKED狀態的線程,都會被加入到該列表。

接下來當線程獲取到對象的 Monitor 時,Monitor 是依靠底層操作系統的 Mutex Lock 來實現互斥的,線程申請 Mutex 成功,則持有該 Mutex,其它線程將無法獲取到該 Mutex。

如果線程調用 wait() 方法,就會釋放當前持有的 Mutex,并且該線程會進入WaitSet集合(也可稱為等待隊列)中,等待下一次被喚醒。此時線程會處于WAITING或者TIMEDWAITING狀態,

如果當前線程順利執行完方法,也將釋放 Mutex。

總的來說,就是同步鎖在這種實現方式中,因 Monitor 是依賴于底層的操作系統實現,存在用戶態內核態之間的切換(可以理解為上下文切換),所以增加了性能開銷。

鎖升級

為了提升性能,JDK1.6 引入了偏向鎖、輕量級鎖、重量級鎖概念,來減少鎖競爭帶來的上下文切換,而正是新增的Java對象頭實現了鎖升級功能。

所謂鎖升級,就是指

>Synchronized 同步鎖初始為偏向鎖,隨著線程競爭越來越激烈,偏向鎖升級到輕量級鎖,最終升級到重量級鎖。

偏向鎖

偏向鎖主要用來優化同一線程多次申請同一個鎖的競爭,也就是現在的Synchronized鎖實際已經擁有了可重入鎖的功能。

為什么要有偏向鎖?因為在我們的應用中,可能大部分時間是同一個線程競爭鎖資源(比如單線程操作一個線程安全的容器),如果這個線程每次都要獲取鎖和釋放鎖,那么就在不斷的從內核態用戶態之間切換。

那么有了偏向鎖,當一個線程再次訪問這個同步代碼或方法時,該線程只需去對象頭中去判斷一下是否當前線程是否持有該偏向鎖就可以了。

一旦出現其它線程競爭鎖資源時,偏向鎖就會被撤銷。偏向鎖的撤銷需要等待全局安全點(JVM的stop the world),暫停持有該鎖的線程,同時檢查該線程是否還在執行該方法,如果是,則升級鎖,反之則被其它線程搶占。

輕量級鎖

當有另外一個線程競爭獲取這個鎖時,由于該鎖已經是偏向鎖,當發現對象頭中的線程 ID 不是自己的線程 ID,就會進行 CAS 操作獲取鎖,如果獲取成功,直接替換對象頭中的線程 ID 為自己的 ID,該鎖會保持偏向鎖狀態;如果獲取鎖失敗,代表當前鎖有一定的競爭,偏向鎖將升級為輕量級鎖。

輕量級鎖適用于線程交替執行同步塊的場景,絕大部分的鎖在整個同步周期內都不存在長時間的競爭。

輕量級鎖也支持自旋,因此其他線程再次爭搶時,如果CAS失敗,將不再會進入阻塞狀態,而是不斷自旋。

之所以自旋更好,是因為之前說了,默認線程持有鎖的時間都不會太長,如果線程被掛起阻塞可能代價會更高。

如果自旋鎖重試之后搶鎖依然失敗,那么同步鎖就會升級至重量級鎖。

重量級鎖

在這個狀態下,未搶到鎖的線程都會進入 Monitor,之后會被阻塞在WaitSet集合中,也就變成了優化之前的Synchronized鎖。

JVM參數優化

偏向鎖升級為輕量級鎖時,會發生stop the world,如果系統常常是多線程競爭,那么禁止偏向鎖也許是更好的選擇,可以通過以下JVM參數進行優化:

// 關閉偏向鎖(默認打開)
-XX:-UseBiasedLocking
// 設置重量級鎖
-XX:+UseHeavyMonitors

輕量級鎖擁有自旋鎖的功能,那么如果線程持有鎖的時間很長,那么競爭的線程也會常常處于自旋狀態,占用系統 CPU ,增加系統開銷,那么此時關閉自旋鎖的優化可以更好一些:

-XX:-UseSpinning

上述內容就是Java中Synchronized的原理是什么,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女