JAVA JUC-01

207 阅读1分钟

内存可见性问题,当多个线程操作共享数据时,彼此不可见.

下面的代码显示了内存不可见

package com.atguigu.juc;

import com.sun.xml.internal.bind.v2.model.annotation.RuntimeAnnotationReader;

public class TestVolatile {


    public static void main(String[] args) {
        ThreadDemo td = new ThreadDemo();
        Thread thread = new Thread(td);
        thread.start();

        while (true) {
            /*
             * while 其实调用的是系统底层的代码,它的执行效率非常的高 , 搞到main 线程没有机会去底层拿到数据 所以 flag 一直是false
             * 这就产生了类存可见性的问题
             */
            if (td.isFlag()) {
                System.out.println("================");
                break;
            }
        }
    }
}


class ThreadDemo implements Runnable {

    private  boolean flag = false;

    @Override
    public void run() {
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        flag = true;
        System.out.println("flag = " + isFlag());
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag (boolean flag) {
        this.flag = flag;
    }
}

输出结果:
flag = true
main 线程没有读到 子线程更改后的 flage的值
造成的原因: while 其实调用的是系统底层的代码,它的执行效率非常的高 , 搞到main 线程没有机会去底层拿到数据 所以 flag 一直是false这就产生了类存可见性的问题.
解决 1 : 同步锁可以解决问题 (synchronized 会刷新缓存) , 但是效率会降低(多线程会阻塞).
synchronized (td) {
    if (td.isFlag()) {
        System.out.println("================");
        break;
    }
}
输出结果:
================
flag = true
解决2 : volatile 关键字: 当多个线程进行操作共享数据时,可以保持内存中的数据可见性.(线程都是直接操作主存中数据) 保持一致性.
 private volatile   boolean flag = false;