您好,登錄后才能下訂單哦!
這篇文章主要介紹了Java線程安全中的有序性是什么的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇Java線程安全中的有序性是什么文章都會有所收獲,下面我們一起來看看吧。
什么是有序性
在開發中,我們通常按照從上到下的順序編寫程序指令,并且希望cpu和編譯器按照我們預先編寫的順序去執。但往往cpu和編譯器為了提高性能、優化指令的執行順序,會將我們編寫好的程序指令進行重排序。
此時如果是在單線程狀態下,無論是否進行了重排序都不會影響程序最終的結果
而有序性是指在多線程環境下就可能會由于程序指令重排序后導致最終結果與預期不符的情況
我們以單例模式中的雙重檢驗鎖為例
利用new關鍵字創建一個對象實際上是執行了三個操作
分配內存空間
在內存上(執行構造方法)初始化對象
將初始化后的對象提交給引用(對象引用指向分配好的內存空間地址)
但是當我們在運行程序時,編譯器對程序進行重排序優化,經常會將2和3兩個步驟進行調換。
// 雙重檢驗鎖 public class Singleton { static Singleton instance; static Singleton getInstance(){ if (instance == null){ synchronized(Singleton.class){ if (instance == null){ instance = new Singleton(); } } } return instance; } }
上述雙重檢驗鎖,在第一次校驗instance是否為null時如果不為null,則不用進行后續的初始化的下面的加鎖操作,大幅的提高了synchronized的性能。但是在多線程狀態下執行上述創建對象的程序,就可能會出現創建的對象instance雖然不為null,但是它可能還沒有初始化但是卻指向了某片內存空間。
我們就下圖進行分析
我們假設A和B兩條線程同時創建對象,那么上述的A線程創建instance時為其分配內存空間,正確來講應該先對instance進行初始化然后將內存地址交給instance,但是由于重排序,卻在初始化之前提交了內存地址。那么當線程切換到B,B就會認為instance是一個創建完成的對象就會返回。
雙重檢驗鎖的有序性就體現在,創建對象的三個操作被重排序之后可能執行順序會變成先提交內存地址再初始化導致對象創建失敗
解決有序性?
Volatile修飾保證有序性
使用Synchtonized加鎖保證有序性
使用Lock加鎖保證有序性
關于“Java線程安全中的有序性是什么”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“Java線程安全中的有序性是什么”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。