深入了解多线程之可见性
最近在深入学习多线程的知识在此记录一下
并发编程三大特性有:可见性,有序性,原子性
可见性验证代码:
public class Visibility { private static /** volatile */ boolean flag = true; private static void m(){ System.out.println("m start"); while (flag){ } System.out.println("m end"); } public static void main(String[] args) throws Exception{ new Thread(Visibility::m,"t1").start(); Thread.sleep(1); flag = false; }
在这段代码中,按照正常的逻辑 m end 是应该会被打印的
但是因为多线程时,一个线程取到该值后有存在只读取缓存中的值内容的情况,就导致了程序会陷入死循环,而不会打印 m end的情况。
当然该情况不是每次都发生,可以多试几次。
当加入了 volatile关键字后即可保证 每一次 flag的值都可以及时的被刷新。
但是当 volatile 修饰对象时,将只保证对象引用的可见性,而不保证对象中属性的可见性,代码如下:
public class Visibility02 { private static class A{ boolean flag = true; void m(){ System.out.println("m start"); while (flag){} System.out.println("m end"); } } private volatile static A a = new A(); public static void main(String[] args) throws Exception{ new Thread(a::m,"t1").start(); Thread.sleep(1); a.flag = false; }
所以当我们想保证对象中的属性的可见性时需要用volatile去修饰该属性.