您好,登錄后才能下訂單哦!
怎樣深入理解Java多線程與并發框中的synchronized 關鍵字,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
對象頭 32位JVM的對象頭
用于實例對象方法(對象是鎖) 用于靜態方法(類是鎖) 用于同步代碼塊(同步代碼塊是鎖)
鎖:就在對象頭中
Java 虛擬機中的同步(Synchronization)基于 進入enter 和 退出exit 監視器(Monitor)對象 實現, 無論是顯式同步(有明確的 monitorenter 和 monitorexit 指令,即同步代碼塊)還是隱式同步都是如此。在 Java 語言中,同步用的最多的地方可能是被 synchronized 修飾的同步方法。同步方法 并不是由 monitorenter 和 monitorexit 指令來實現同步的,而是由方法調用指令讀取運行時常量池中方法的 ACC_SYNCHRONIZED 標志來隱式實現的,關于這點,稍后詳細分析。下面先來了解一個概念Java對象頭,這對深入理解synchronized實現原理非常關鍵。
1. 對象加鎖: 使用 monitorenter 和 monitorexit 指令分別獲取控制權和釋放控制權。
2. 方法加鎖:
方法級的同步是隱式,即無需通過字節碼指令來控制的,它實現在方法調用和返回操作之中。JVM可以從方法常量池中的方法表結構(method_info Structure) 中的 ACC_SYNCHRONIZED 訪問標志區分一個方法是否同步方法。當方法調用時,調用指令將會檢查方法的 ACC_SYNCHRONIZED 訪問標志是否被設置,如果設置了,執行線程將先持有monitor(虛擬機規范中用的是監視器一詞), 然后再執行方法,最后再方法完成(無論是正常完成還是非正常完成)時釋放monitor。在方法執行期間,執行線程持有了monitor,其他任何線程都無法再獲得同一個monitor。如果一個同步方法執行期間拋 出了異常,并且在方法內部無法處理此異常,那這個同步方法所持有的monitor將在異常拋到同步方法之外時自動釋放。
背景:Java 6之后,為了減少獲得鎖和釋放鎖所帶來的性能消耗,引入了 偏向鎖 和 輕量級鎖。 鎖的狀態:無鎖狀態、偏向鎖、輕量級鎖、重量級鎖。 鎖從 偏向鎖 -> 輕量級鎖 -> 重量級鎖 的鎖升級是單向的、不可逆的,沒有 鎖降級 這一說。
1. 偏向鎖
因此為了減少同一線程獲取鎖(會涉及到一些CAS操作,耗時)的代價而引入偏向鎖。偏向鎖的核心思想是,如果一個線程獲得了鎖,那么鎖就進入偏向模式,此時Mark Word 的結構也變為偏向鎖結構,當這個線程再次請求鎖時,無需再做任何同步操作,即獲取鎖的過程,這樣就省去了大量有關鎖申請的操作,從而也就提供程序的性能。
2. 輕量級鎖
輕量級鎖所適應的場景是 線程交替執行同步塊 的場合,如果存在 同一時刻訪問同一鎖 的場合,就會導致輕量級鎖膨脹為重量級鎖。
3. 自旋鎖
自旋鎖是樂觀的一種表現,樂觀的認為很大概率是能夠獲得鎖的。(根據阿里巴巴Java開發規范:如果每次訪問沖突的概率小于 20%,推薦使用樂觀鎖,否則使用悲觀鎖。樂觀鎖的重試次數不得小于3次。)
4. 重入鎖
從互斥鎖的設計上來說,當一個線程試圖操作一個由其他線程持有的對象鎖的臨界資源時,將會處于阻塞狀態,但當一個線程再次請求自己持有對象鎖的臨界區的資源時,這種情況屬于 *重入鎖,請求將會成功,在java中synchronized是基于原子性的內部鎖機制,是可重入的,因此在一個線程調用synchronized方法的同時在其方法體內部調用該對象另一個synchronized方法,也就是說一個線程得到一個對象鎖后再次請求該對象鎖,是允許的,這就是synchronized的可重入性。
5. 鎖消除
消除鎖是虛擬機另外一種鎖的優化,這種優化更徹底,Java虛擬機在JIT編譯時(可以簡單理解為當某段代碼即將第一次被執行時進行編譯,又稱即時編譯),通過對運行上下文的掃描,去除不可能存在共享資源競爭的鎖,通過這種方式消除沒有必要的鎖,可以節省毫無意義的請求鎖時間,如下StringBuffer的append是一個同步方法,但是在add方法中的StringBuffer屬于一個局部變量,并且不會被其他線程所使用,因此StringBuffer不可能存在共享資源競爭的情景,JVM會自動將其鎖消除。
中斷與synchronized: 事實上線程的中斷操作對于正在等待獲取的鎖對象的synchronized方法或者代碼塊并不起作用,也就是對于synchronized來說,如果一個線程在等待鎖,那么結果只有兩種,要么它獲得這把鎖繼續執行,要么它就保存等待,即使調用中斷線程的方法,也不會生效。
看完上述內容,你們掌握怎樣深入理解Java多線程與并發框中的synchronized 關鍵字的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。