Java多线程 synchronized与可见性的关系以及可见性问题总结
@[toc] 能保证可见性的措施 除了volatile 可以让变量保证可见性外. 如下这篇文章中,介绍的happens-before九大规则. 都是能够保证可见性的. 其中就包含了锁操作(synchronized 和 lock) 和 volatile 修饰的变量 https://javaweixin6.blog.csdn.net/article/details/108423590 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之前执行的代码也是可见的 .