天天看點

Java并發程式設計三個性質:原子性、可見性、有序性

并發程式設計 并發程式要正确地執行,必須要保證其具備原子性、可見性以及有序性;隻要有一個沒有被保證,就有可能會導緻程式運作不正确

線程不安全在編譯、測試甚至上線使用時,并不一定能發現,因為受到當時的CPU排程順序,線程個數、指令重排的影響,偶然觸發

線程安全的定義 比如說一個類,不論通過怎樣的排程執行順序,并且調用處不用對其進行同步操作,其都能表現出正确的行為,則這個類就是線程安全的

并發程式設計三個概念 原子性 : 一個操作或多個操作要麼全部執行 且執行過程不被中斷 ,要麼不執行

可見性 : 多個線程修改同一個共享變量時,一個線程修改後,其他線程能馬上獲得修改後的值

有序性 : 程式執行的順序按照代碼的先後順序執行

具體實作

可以通過  synchronized 和 Lock 實作原子性,因為synchronized和Lock能夠保證任一時刻 隻有一個線程 通路該代碼塊

Java提供了 volatile關鍵字 保證可見性 synchronized和lock也可保證可見性,在加鎖時其他線程無法通路共享資源

可以通過 volatile 關鍵字來保證一定的“有序性”

java提供的解決線程不安全的類: java.util.concurrent.atomic

Atomic 類并不使用同步鎖,而是采用CAS操作,每次對值進行修改時,先判斷其預期值與記憶體值是否相同,若相同則修改,否則不修改

優點 不加鎖,性能較快 缺點 高并發情況下,出錯機率越大,長時間CAS不成功,導緻CPU消耗過大

注:此種方法是樂觀鎖,即操作前認為此次操作不會出現競态,不加鎖,隻在最後寫入主存時進行判斷 警:ABA問題,當一個值原來是A,被某個線程改成B,又被另個線程改成A,此時CAS操作判斷不出已經發生變化,java中使用版本号來解決此問題

内置鎖 java中以 synchronized 關鍵字來支援原子性 重入鎖 當一個線程已獲得鎖時,再繼續試圖獲得它已經得到的鎖時,這個請求是成功的。 重入鎖意味着鎖的粒度是線程,而不是每個方法調用

重入實作方法:為每個鎖關聯一個 計數器 和 所有者線程 ,當計數值為0,即目前沒有任何線程獲得鎖,當線程請求時,JVM記下鎖的持有者,計數值置1,當該線程又請求鎖時,計數值遞增,等其釋放,遞減到0,鎖被釋放。 作用 避免死鎖

繼續閱讀