java 關鍵字集錦之volatile、synchronized

爲了解決線程併發的問題,在語言內部引入了 同步塊(synchronized) 和 volatile 關鍵字機制;

關鍵字:synchronized

同步塊:synchronized,所有加上synchronized的塊語句,在多線程訪問的時候,同一時刻只能有一個線程能夠用

synchronized 修飾的方法 或者 代碼塊。

作用:保證同一時刻最多隻有1個線程執行 被Synchronized修飾的方法 / 代碼,其他線程 必須等待當前線程執行完該方法 / 代碼塊後才能執行該方法 / 代碼塊,解決多線程中的併發同步問題;

使用實例:

private static ThreadLocal<SimpleDateFormat> FORMAT_DATE_DB_THREADLOCAL = new ThreadLocal<SimpleDateFormat>() {
        protected synchronized SimpleDateFormat initialValue() {
            SimpleDateFormat sd = new SimpleDateFormat(
                    "yyyyMMdd");
            sd.setLenient(false);
            return sd;
        }
    };

關鍵字:volatile

作用:保證數據在多線程間的內存可見性;

在多線程環境下,某個共享變量如果被其中一個線程給修改了,其他線程能夠立即知道這個共享變量已經被修改了,當其他線程要讀取這個變量的時候,最終會去內存中讀取,而不是從自己的工作空間中讀取。

也就是說,使用volatile關鍵字後,會有如下效果:

1、每次對變量的修改,都會引起處理器緩存(工作內存)寫回到主存;

2、一個工作內存回寫到主存會導致其他線程的處理器緩存(工作內存)無效。

事例:

不使用volatile,執行出現死循環:

public class TestWithoutVolatile {
    private static boolean bChanged;
    public static void main(String[] args) throws InterruptedException {
        new Thread() {
            @Override
            public void run() {
                for (; ; ) {
                    if (bChanged == !bChanged) {
                        System.out.println("!=");
                        System.exit(0);
                    }
                }
            }
        }.start();
        Thread.sleep(1);
        new Thread() {
            @Override
            public void run() {
                for (; ; ) {
                    bChanged = !bChanged;
                }
            }
        }.start();
    }
}

使用volatile,程序輸出!=,然後馬上退出。

public class TestWithVolatile {
    private static volatile boolean bChanged;

    public static void main(String[] args) throws InterruptedException {
        new Thread() {
            @Override
            public void run() {
                for (; ; ) {
                    if (bChanged == !bChanged) {
                        System.out.println("!=");
                        System.exit(0);
                    }
                }
            }
        }.start();
        Thread.sleep(1);
        new Thread() {
            @Override
            public void run() {
                for (; ; ) {
                    bChanged = !bChanged;
                }
            }
        }.start();
    }
}

PS重要文章:https://www.jianshu.com/p/2ed498b43628 (詳解synchronized

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章