深入了解多线程之可见性

最近在深入学习多线程的知识在此记录一下
并发编程三大特性有:可见性,有序性,原子性

可见性验证代码:

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去修饰该属性.

 

posted @ 2022-03-03 09:12  xdq123  阅读(58)  评论(0编辑  收藏  举报