中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

如何用JAVA語言分析雙重檢查鎖定

發布時間:2022-01-18 15:03:04 來源:億速云 閱讀:120 作者:柒染 欄目:網絡管理

這篇文章跟大家分析一下“如何用JAVA語言分析雙重檢查鎖定”。內容詳細易懂,對“如何用JAVA語言分析雙重檢查鎖定”感興趣的朋友可以跟著小編的思路慢慢深入來閱讀一下,希望閱讀后能夠對大家有所幫助。下面跟著小編一起深入學習“如何用JAVA語言分析雙重檢查鎖定”的知識吧。

1、雙重檢查鎖定

在程序開發中,有時需要推遲一些高開銷的對象初始化操作,并且只有在使用這些對象時才進行初始化,此時可以采用雙重檢查鎖定來延遲對象初始化操作。雙重檢查鎖定是設計用來減少并發系統中競爭和同步開銷的一種軟件設計模式,在普通單例模式的基礎上,先判斷對象是否已經被初始化,再決定要不要加鎖。盡管雙重檢查鎖定解決了普通單例模式的在多線程環境中易出錯和線程不安全的問題,但仍然存在一些隱患。下面以JAVA語言源代碼為例,分析雙重檢查鎖定缺陷產生的原因以及修復方法。

2、 雙重檢查鎖定的危害

雙重檢查鎖定在單線程環境中并無影響,在多線程環境下,由于線程隨時會相互切換執行,在指令重排的情況下,對象未實例化完全,導致程序調用出錯。

3、示例代碼

示例源于Samate Juliet Test Suite for Java v1.3 (https://samate.nist.gov/SARD/testsuite.php),源文件名:CWE609_Double_Checked_Locking__Servlet_01.java。

3.1缺陷代碼

如何用JAVA語言分析雙重檢查鎖定

上述代碼行23行-38行,程序先判斷 stringBad 是否為 null,如果不是則直接返回該 String 對象,這樣避免了進入 synchronized 塊所需要花費的資源。當 stringBad 為 null 時,使用 synchronized 關鍵字在多線程環境中避免多次創建 String 對象。在代碼實際運行時,以上代碼仍然可能發生錯誤。

對于第33行,創建 stringBad 對象和賦值操作是分兩步執行的。但 JVM 不保證這兩個操作的先后順序。當指令重排序后,JVM 會先賦值指向了內存地址,然后再初始化 stringBad 對象。如果此時存在兩個線程,兩個線程同時進入了第27行。線程1首先進入了 synchronized 塊,由于 stringBad 為 null,所以它執行了第33行。當 JVM 對指令進行了重排序,JVM 先分配了實例的空白內存,并賦值給 stringBad,但這時 stringBad 對象還未實例化,然后線程1離開了 synchronized 塊。當線程2進入 synchronized 塊時,由于 stringBad 此時不是 null ,直接返回了未被實例化的對象(僅有內存地址值,對象實際未初始化)。后續線程2調用程序對 stringBad 對象進行操作時,此時的對象未被初始化,于是錯誤發生。

使用360代碼衛士對上述示例代碼進行檢測,可以檢出“雙重檢查鎖定”缺陷,顯示等級為中。在代碼行第27行報出缺陷,如圖1所示:


如何用JAVA語言分析雙重檢查鎖定

圖1:“雙重檢查鎖定”的檢測示例

3.2 修復代碼

如何用JAVA語言分析雙重檢查鎖定

在上述修復代碼中,在第23行使用 volatile 關鍵字來對單例變量 stringBad 進行修飾。 volatile 作為指令關鍵字確保指令不會因編譯器的優化而省略,且要求每次直接讀值。

由于編譯器優化,代碼在實際執行的時候可能與我們編寫的順序不同。編譯器只保證程序執行結果與源代碼相同,卻不保證實際指令的順序與源代碼相同,在單線程環境中并不會出錯,然而一旦引入多線程環境,這種亂序就可能導致嚴重問題。 volatile 關鍵字就可以從語義上解決這個問題,值得關注的是 volatile 的禁止指令重排序優化功能在 Java 1.5 后才得以實現,因此1.5 前的版本仍然是不安全的,即使使用了 volatile 關鍵字。

使用360代碼衛士對修復后的代碼進行檢測,可以看到已不存在“雙重檢查鎖定”缺陷。如圖2:


如何用JAVA語言分析雙重檢查鎖定

圖2:修復后檢測結果

4 、如何避免雙重檢查鎖定

要避免雙重檢查鎖定,需要注意以下幾點:

(1)使用 volatile 關鍵字避免指令重排序,但這個解決方案需要 JDK5 或更高版本,因為從JDK5 開始使用新的 JSR-133 內存模型規范,這個規范增強了 volatile 的語義。

(2)基于類初始化的解決方案。

如何用JAVA語言分析雙重檢查鎖定JVM在類的初始化階段(即在Class被加載后,且被線程使用之前),會執行類的初始化。在執行類的初始化期間,JVM會去獲取一個鎖。這個鎖可以同步多個線程對同一個類的初始化。

關于如何用JAVA語言分析雙重檢查鎖定就分享到這里啦,希望上述內容能夠讓大家有所提升。如果想要學習更多知識,請大家多多留意小編的更新。謝謝大家關注一下億速云網站!

向AI問一下細節

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

AI

顺义区| 安新县| 兰州市| 海城市| 深泽县| 宽甸| 闵行区| 吴堡县| 新兴县| 汝南县| 辽阳市| 鄢陵县| 兴宁市| 沅江市| 南阳市| 昂仁县| 鄄城县| 牡丹江市| 榆中县| 府谷县| 阿克苏市| 文昌市| 牙克石市| 于田县| 乐亭县| 子长县| 兴安盟| 万盛区| 松桃| 沛县| 文水县| 江阴市| 长治市| 锡林郭勒盟| 沿河| 河东区| 海林市| 荔浦县| 奇台县| 昌吉市| 维西|