volatile的原理和使用

1.對(duì)線程的可見性

Java的volatile關(guān)鍵字聲明使變量對(duì)不同線程具有可見性。程序在多線程操作non-volatile變量時(shí),為了提升性能,每個(gè)線程會(huì)將變量從主內(nèi)存復(fù)制到CPU緩存。如果有多個(gè)CPU核心,每個(gè)線程可能在不同的CPU上運(yùn)行。這意味著每個(gè)線程的CPU緩存的變量的值可能不一樣。如圖所示:

import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

public class VolatileTest {
    private static Logger logger = Logger.getLogger(VolatileTest.class.getName());
    private static volatile int Counter = 0;

    public static void main(String[] args) {
        new ChangeListener().start();
        new ChangeMaker().start();
    }

    static class ChangeListener extends Thread {
        @Override
        public void run() {
            int localValue = Counter;
            while (localValue < 2) {
                //不加volatile Counter永遠(yuǎn)等于0,加volatile之后Counter會(huì)發(fā)生變化
                if (localValue != Counter) {
                    logger.info(Thread.currentThread().getName() + " 值被修改了 Counter = " + Counter);
                    localValue = Counter;
                }
            }
        }
    }

    static class ChangeMaker extends Thread {
        @Override
        public void run() {

            int localValue = Counter;
            while (Counter < 2) {
                logger.info(Thread.currentThread().getName() + " Counter+1 = " + (localValue + 1));
                Counter = ++localValue;
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

不加volatile 運(yùn)行結(jié)果:

二月 22, 2019 12:06:56 上午 VolatileTest$ChangeMaker run
信息: Thread-2 Counter+1 = 1
二月 22, 2019 12:06:57 上午 VolatileTest$ChangeMaker run
信息: Thread-2 Counter+1 = 2

加了volatile 運(yùn)行結(jié)果:

二月 22, 2019 12:05:30 上午 VolatileTest$ChangeMaker run
信息: Thread-2 Counter+1 = 1
二月 22, 2019 12:05:30 上午 VolatileTest$ChangeListener run
信息: Thread-1 值被修改了 Counter = 1
二月 22, 2019 12:05:31 上午 VolatileTest$ChangeMaker run
信息: Thread-2 Counter+1 = 2
二月 22, 2019 12:05:31 上午 VolatileTest$ChangeListener run
信息: Thread-1 值被修改了 Counter = 2

2.對(duì)線程的有序性

volatile可以禁止指令重排序,volatile標(biāo)識(shí)的變量,會(huì)有內(nèi)存屏障,指令重排序時(shí)就不能把后面的指令重排序到內(nèi)存屏障之前的位置,這樣就保證不同的代碼塊只能串行執(zhí)行,不能同步執(zhí)行,這樣就保證了線程的有序性。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容