目录

大橙子

VX:ZzzChChen
Phone:13403656751
Email:zxydczzs@gmail.com

volatile关键字与内存可见性

package com.zxy.demo.thread;

import lombok.Data;

/**
 * @author ZhangXiaoYu
 * @date 2021/9/2 9:26
 */
public class ThreadDemo1 {
    //volatile关键字与内存可见性
    /*
    * new一个线程子类实例并start,线程内部睡眠200毫秒后将flag设置为true
    * 主线程使用while循环,如果线程子类的成员变量flag为true时,输出一句话后break出循环。
    * 问题1:在主线程while循环时,flag已经为true,却没有跳出循环,为什么?
    * 这是内存可见性的问题。当多个线程操作共享数据时,彼此不可见。
    * 基本可以理解为,ThreadDemo线程先从主存中把数据读取过来,读取到的是false,然后修改为true,就在还未来得及把true同步到主存
    * 时,main进来了,这是main读取到的还是false,所以形成死循环,就在main循环时,ThreadDemo线程把true同步到主存了,所以
    * ThreadDemo线程中输出语句打印的是true。
    *
    * 要解决这个问题,可以加锁。
    * */
    public static void main(String[] args) throws InterruptedException { //这个线程是用来读取flag的值的
        ThreadDemo threadDemo = new ThreadDemo();
        Thread thread = new Thread(threadDemo);
        thread.start();
        //加锁处理
        /*
        * 加了锁,就可以让while循环每次都从主存中去读取数据,这样就能读取到true了,但是一旦加了锁,每次只能有一个线程访问,
        * 当一个线程持有锁时,其他的就会阻塞,效率就非常低了,不想加锁,又要解决内存可见性问题,那么就可以使用volatile关键字。
        * */
//        while (true) {
//            synchronized (threadDemo){
//                if (threadDemo.isFlag()) {
//                    System.out.println("主线程读取到的flag = " + threadDemo.isFlag());
//                    break;
//                }
//            }
//        }
        //原始步骤
        while (true) {
            if (threadDemo.isFlag()) {
                System.out.println("主线程读取到的flag = " + threadDemo.isFlag());
                break;
            }
        }
    }
}
@Data
class ThreadDemo implements Runnable { //这个线程是用来修改flag的值的

    /*
    * volatile关键字:当多个线程操作共享数据时,可以保证内存中的数据可见,用这个关键字修饰共享数据,就会及时的把线程缓存中的数据刷新到
    * 主存中去,也可以理解为,就是直接操作主存中的数据,所以在不使用锁的情况下,可以使用volatile。
    * 这样就可以解决内存可见性的问题了。
    *
    * volatile和synchronized的区别
    *   volatile不具备互斥性(当一个线程持有锁时,其他线程进不来,这就是互斥性)
    *   volatile不具备原子性。
    *
    * */
    //volatile
    public volatile boolean flag = false;
    //原始步骤
//    public boolean flag = false;

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

参考文献:https://www.jianshu.com/p/1f19835e05c0


标题:volatile关键字与内存可见性
作者:zzzzchen
地址:https://www.dczzs.com/articles/2021/09/02/1630547214988.html