@[toc]java
能保證可見性的措施
除了volatile 可讓變量保證可見性外.緩存
以下這篇文章中,介紹的happens-before九大規則. 都是可以保證可見性的. 其中就包含了鎖操做(synchronized 和 lock) 和 volatile 修飾的變量安全
https://javaweixin6.blog.csdn.net/article/details/108423590app
synchronized做用的昇華
- synchronized 關鍵字不單單保證了其代碼塊中的原子性 ,也保證了可見性. 例如以下代碼中的i++操做 , 使用了synchronized 代碼塊保護起來, 使得兩個線程對其相加的時候, 能夠正確的得出20萬的結果.
這個結果不單單是保證了其i相加時候的原子性. 也說明保證了其可見性. 不然一個線程加完了以後, 另一個線程沒有獲取i的最新的值的話, 也會致使相加的結果變少. - synchronized 不單單讓被保護的代碼安全, 還會保證對synchronized 修飾的代碼執行完畢以後, 下一個synchronized 進入以前, 整個synchronized 保護的代碼塊,都會被以後執行的代碼看獲得. 而且synchronized 以前的全部的代碼也會被看到 . 以下面這幅圖, 線程B拿到鎖以後, 對於線程A的全部的操做都是可見的. 這是一個連帶效應.
以下的代碼中, 對可見性的代碼進行了修改. 把賦值操做的方法中, 最後一個變量的賦值, 加上了synchronized修飾. 打印的方法中, 第一行代碼加上了synchronized修飾. 這樣就保證了原子性和可見性. 寫線程在執行完成d=6的時候, 會釋放鎖. 打印的線程得到鎖的時候, 就能知道寫線程的全部的操做, 得到其最新的值.
完整的代碼以下.
package com.thread.jmm; /** * 類名稱:FieldVisibility * 類描述: 演示可見性問題 * * @author: https://javaweixin6.blog.csdn.net/ * 建立時間:2020/9/5 14:31 * Version 1.0 */ public class FieldVisibility { int a = 1; int b = 2; int c = 3; int d = 4; //給a 賦值, 並把值給b private void change() { a = 3; b = a; c = a; synchronized (this) { d = 6; } } /** * 打印出a b */ private void print() { synchronized (this) { int aa = a ; } int bb = b ; int cc = c ; int dd = d ; System.out.println("b=" + b + ";a=" + a); } public static void main(String[] args) { while (true) { FieldVisibility test = new FieldVisibility(); new Thread(() -> { try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } //給 a b 從新賦值 test.change(); }).start(); new Thread(() -> { try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } //給 a b 打印出來 test.print(); }).start(); } } }
可見性總結
- 演示什麼是可見性 https://javaweixin6.blog.csdn.net/article/details/108419450
- 爲何會有可見性問題: CPU的多級緩存, 致使沒有從主內存中獲取最新值 . https://javaweixin6.blog.csdn.net/article/details/108421939
- JMM的抽象 : 主內存和本地內存. https://javaweixin6.blog.csdn.net/article/details/108422267
- happens-before原則與規則https://javaweixin6.blog.csdn.net/article/details/108422677 https://javaweixin6.blog.csdn.net/article/details/108423590
- volatile 關鍵字 https://javaweixin6.blog.csdn.net/article/details/108431303
- 能保證可見性的措施, 與happens-before原則一致.
- 對synchronized認識的昇華, 不單單是保證了原子性, 也保證了可見性. 同時 對於synchronized修飾的代碼, synchronized以前執行的代碼也是可見的 .