和我一起迎接明天的太阳吧

klaus08

焦虑源于行动的匮乏

volatile

代码实例

如下代码中,"Wow"是永远不会被打印出来的,因为所有的共享变量都存储于主内存,这里所说的变量指的是实例变量和类变量,不包含局部变量,因为局部变量是线程私有的,因此不存在竞争问题,flag变量只在apple.start创建的线程中。


package com.klaus.thread;

public class VolatileTest {
    public static void main(String[] args) {
        Apple apple = new Apple();
        apple.start();
        while (true) {
            // synchronized (apple){
            if (apple.isFlag()) {
                System.out.println("Wow");
            }
            // }
        }
    }

}

class Apple extends Thread {
    private volatile boolean flag = false;

    public boolean isFlag() {
        return flag;
    }

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

可见性的解决方案

1.synchronized

因为某一个线程进入synchronized代码块前后,线程会获得锁,清空工作内存,从主内存拷贝共享变量最新的值到工作内存成为副本,执行代码,将修改后的副本的值刷新回主内存中,线程释放锁。
而获取不到锁的线程会阻塞等待,所以变量的值肯定一直都是最新的。


2.volatile

每个线程操作数据的时候会把数据从主内存读取到自己的工作内存,如果他操作了数据并且写了,其他已经读取的线程的变量副本就会失效了,需要都数据进行操作又要再次去主内存中读取了。

volatile保证不同线程对共享变量操作的可见性,也就是说一个线程修改了volatile修饰的变量,当修改写回主内存时,另外一个线程立即看到最新的值。

是不是看着加一个关键字很简单,但实际上他在背后含辛茹苦默默付出了不少,我从计算机层面的缓存一致性协议解释一下这些名词的意义。



源自https://mp.weixin.qq.com/s?__biz=MzAwNDA2OTM1Ng==&mid=2453142004&idx=1&sn=81ccddb6c8b37114c022c4ad50368ecf&scene=21#wechat_redirect

posted @ 2021-10-10 22:36  klaus08  阅读(35)  评论(0编辑  收藏  举报