Synchronized 和volatile的異同

1. 簡介

我常常使用synchronized和volatile在我們的程序中保證在并發(fā)中數(shù)據(jù)的安全,但是我們怎么理解他們了??

2.JMM(Java Memory Model)

JMM 是一個JVM對主內(nèi)存和緩存和CPU之間的關(guān)系做了簡化抽象,在實際情況下并不存在.在下圖 ThreadStack 對應(yīng)緩存和CPU的寄存器,而Heap對應(yīng)主內(nèi)存


image.png

3. 異同

  1. Synchronized 是修飾代碼塊和方法的,而volatile是修飾變量的
  2. Synchronized 是保證原子性和有序性和可見性,而volatile只有 有序性和可見性
    3 Synchronized 會導(dǎo)致線程上下文切換,而 volatile不會,這就會使volatile的效率高于synchronized
  3. synchronized是在讀入變量的時候,會清空當(dāng)前線程的緩存,直接從主內(nèi)存中讀取,而volatile是在其中有一個線程進(jìn)行寫操作結(jié)束的時候,會通知其他線程他們緩存失效,需要從主內(nèi)存中讀取,用volatile修飾的變量所有的寫操作都優(yōu)先于讀操作。(任何變量進(jìn)行寫操作的時候都會寫入主內(nèi)存,而讀取就優(yōu)先從緩存中讀取)

4 一個簡單的例子

這個例子我們會在多線程下,執(zhí)行對同一個變量進(jìn)行修改和讀取

4.1 我對寫操作使用synchronized 和讀操作不使用,變量也不用volatile修飾

package liusheng.main.liusheng.main;

import liusheng.main.ConcurrentQueue;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;

public class SynAndVolatile {
    static class TestClass {
        int num = 0;

        public synchronized void add() {
            num++;
        }

        public int getNum() {
            return num;
        }
    }

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(20);
        TestClass testClass = new TestClass();
        IntStream.range(0, 10).boxed().map(i -> (Runnable) () -> {
                    for (int j = 0; j < 10000; j++) {
                        testClass.add();
                    }
                    System.out.println("完成");
                }
        ).forEach(executorService::execute);
        for (; ; ) {
            if (testClass.getNum() == 100000) {
                System.out.println("SUCCESS");
            }
        }
    }


}

4.1 結(jié)果

image.png

我們發(fā)現(xiàn)程序卡主了,讀取不出num的值,也就是main線程是在緩存中讀取的,不是在主內(nèi)存中讀取的,所以發(fā)現(xiàn)不了num值的變化

4.2 我們對num進(jìn)行volatile修飾,其他的還是一樣的

  volatile int num = 0;

4.2 結(jié)果


我們發(fā)現(xiàn)主內(nèi)存檢查到了num值發(fā)生的變化,當(dāng)num值發(fā)生變化的時候會通知其他(含有num副本的現(xiàn)場)線程,這num副本失效,需要從主內(nèi)存從新讀取。

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

相關(guān)閱讀更多精彩內(nèi)容

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