在學習volatile語義的可見性和禁止指令重排序的相關測試中,發現並不能體現出禁止指令重排序的特性
實驗代碼如下
package com.aaron.beginner.multithread.volatiletest; import java.util.concurrent.CountDownLatch; /** * @author * @description 一句話描述該文件的用途 * @date 2017-03-01 */ public class VolatileAndNonVolatileTest { private volatile boolean flag; private int num; public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 5000; i++) { final VolatileAndNonVolatileTest test = new VolatileAndNonVolatileTest(); CountDownLatch latch = new CountDownLatch(2); Thread write = new Thread(() -> { test.write(); latch.countDown(); }); Thread read = new Thread(() -> { test.read(); latch.countDown(); }); write.start(); read.start(); latch.await(); } } private void read() { if (flag) { System.out.println("=" + num * num); } } private void write() { num = 10;//步驟1 flag = true;//步驟2 } }
實驗步驟:
注意關注代碼中flag變量,會分別測試flag變量有volatile修飾和沒有volatile修飾時的輸出情況
本測試代碼主要的功能:
- write方法負責修改num變量,修改后設置flag=true,表示num變量已經修改成功
- read方法負責讀取修改后的num值,並輸入平方
實驗步驟:
- 在循環中每次啟動兩個線程,一個線程負責調用write修改數據,另一個線程負責讀取修改后的值
- 觀察實驗結構
預期結果:
- 當flag沒有volatile修飾的時候,我們本應該期望的是能夠輸出"=100"
- 當flag有volatile修飾的時候,由於有可見性和禁止了指令重排序,每次正常輸出"=100"
實際結果:
- 當flag沒有volatile修飾的時候,多次實驗均沒有發現指令重排序發生(即出現"=0",也就是說write方法中步驟1和步驟2沒有發生重排序(步驟2比步驟1先發生))
- 當flag有volatile修飾的時候(理論上有可見性和禁止了指令重排序,不會出現"=0"),實際上也沒有出現"=0",和1結果一致。
即加了和沒加volatile的結果是一致的
試問各位大神,有知道怎么測試這個volatile,體現禁止了指令重排序的特點和可見性的特點嗎?