###作用
保證不同執行緒對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...