Java 併發程式設計之 volatile 關鍵字

2021-08-27 21:04:02 字數 1647 閱讀 9366

###作用

保證不同執行緒對volatile修飾的變數進行操作時的可見性,即乙個執行緒修改了某個變數的值,這新值對其他執行緒來說是立即可見的。

禁止進行指令重排序。

##volatile 的可見性

public class test_09 

system.out.println("end"); }

public static void main(string args)

}).start();

try catch (interruptedexception e)

t.b = false; }

}

執行結果:

start

然後一直死迴圈阻塞。

我們不是修改了 b 嗎?為什麼還在執行迴圈?

這就是執行緒的可見性問題了。

當把上面**的 boolean 前加上volatile時,

執行結果:

start

endvolatile只是通知 os 底層計算時,cpu 檢查記憶體資料,而不是讓乙個變數在多個執行緒中同步。

volatile通知 os 作業系統底層,在 cpu 計算過程中,都要檢查記憶體中資料的有效性。保證最新的記憶體資料被使用。

##volatile 的非原子性問題

**解讀:

我在 main 方法中啟動了 10 個執行緒,然後通過呼叫 join 方法使得乙個執行緒執行完以後再執行其他執行緒,通過volatile關鍵字可以讓每個執行緒都取到最新的資料 i。

i 初始化為 0 。run 方法就是把 i 加 10000。預想結果 1 個執行緒加 10000,那麼 10 個執行緒加 10 0000。

public class test_10 	}	

public static void main(string args)

}));

} for(thread thread : threads)

for(thread thread : threads) catch (interruptedexception e)

} system.out.println(t.count);

}}

執行結果:

為什麼會是 35694 而不是 10 0000 呢?

這就是執行緒的原子性問題了。

在多執行緒執行的過程中,當執行緒 a 取到 i=2000 時,i 這個值會被快取到快取記憶體中,此時 cpu 中斷,執行緒 b 獲得 cpu 資源並開始計算,此時記憶體中 i 的值還是 2000。因為執行緒 a 還沒有來得及進行加的操作就讓出了 cpu。當執行緒 b 執行 +1 的操作後 i 變為 2001。此時執行緒 a 重新獲得 cpu ,執行 +1 操作。快取中的 i 變為 2001 寫入到記憶體中,把剛才執行緒b 運算的結果覆蓋。這樣的話就相當於倆次迴圈 i 加了 1。發生多次這樣的情況下,得到的結果就會比預想的少了許多。

volatile只能保證可見性,不能保證原子性。

java併發程式設計之Exchanger

exchanger v 可以交換的物件型別 可以在對中對元素進行配對和交換的執行緒的同步點。每個執行緒將條目上的某個方法呈現給 exchange 方法,與夥伴執行緒進行匹配,並且在返回時接收其夥伴的物件。exchanger 可能被視為 synchronousqueue 的雙向形式。exchanger...

java併發程式設計之Synchronized關鍵字

1.synchronized關鍵字使用前介紹 1 使用synchronized關鍵字修飾方法,ps 在這裡要特別需要注意的是,當有兩個或者以上執行緒的時候,其中有乙個執行緒獲取了該方法的物件鎖執行同步方法的時候,其他的執行緒仍然可以訪問其他的非使用synchronized的方法,也就是非同步的了。2...

java併發程式設計之synchronized

上篇部落格沒寫好,排版改了好多次,看著實在頭疼所以就沒準備往下寫了,今天講下同步使用到的關鍵字synchronized,這個關鍵字可以是用在方法上,也可以使用再 塊上,synchronized作用在方法上,它的鎖物件是當前例項物件 public class syncthreadtest implem...