@[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以前执行的代码也是可见的 .