關於volatile的可見性和禁止指令重排序的疑惑


在學習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修飾時的輸出情況

 

本測試代碼主要的功能:

  1. write方法負責修改num變量,修改后設置flag=true,表示num變量已經修改成功
  2. read方法負責讀取修改后的num值,並輸入平方

實驗步驟:

  1. 在循環中每次啟動兩個線程,一個線程負責調用write修改數據,另一個線程負責讀取修改后的值
  2. 觀察實驗結構

預期結果:

  1. 當flag沒有volatile修飾的時候,我們本應該期望的是能夠輸出"=100"
  2. 當flag有volatile修飾的時候,由於有可見性和禁止了指令重排序,每次正常輸出"=100"

實際結果:

  1. 當flag沒有volatile修飾的時候,多次實驗均沒有發現指令重排序發生(即出現"=0",也就是說write方法中步驟1和步驟2沒有發生重排序(步驟2比步驟1先發生))
  2. 當flag有volatile修飾的時候(理論上有可見性和禁止了指令重排序,不會出現"=0"),實際上也沒有出現"=0",和1結果一致。

  即加了和沒加volatile的結果是一致的

 

試問各位大神,有知道怎么測試這個volatile,體現禁止了指令重排序的特點和可見性的特點嗎?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM