IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> volatile原理探究 -> 正文阅读

[Java知识库]volatile原理探究

volatile提供的能力之可见性(一)

前言

java并发面临的三大问题,原子性、可见行、有序性;
1.原子性是指一块代码要不全部执行,并且在执行过程中不被干扰,要不都不执行。
2.可见性是指多线程对共享资源进行操作的时候,共享资源的修改能立刻对其他线程可见。
3.有序性是指java程序的顺序有可能不会按照行的顺序执行,编译器会代码的执行顺序优化,优化后的代码可能就不会按照代码顺序执行了,但是这种优化并不是对所有的代码都会生效的,只要遵循happen as if serial语意,就有可能对代码优化;这样看起来没有问题,但是针对一些特殊的场景就会有问题,比如懒汉模式的单例,就有可能出现问题,这个场景会在后面展示。

可见性能力

volatile可以提供共享资源的可见性,先通过一段代码的执行验证volatile的效果。

public class Test3 {
    private boolean flag = true;

    public void refresh(){
        flag = false;
        System.out.println(Thread.currentThread().getName() + "修改flag");
    }

    public void load(){
        System.out.println(Thread.currentThread().getName() + "开始执行...");
        while (flag){
//            System.out.println(flag);
        }
        System.out.println(Thread.currentThread().getName() + "跳出循环");
    }

    public static void main(String[] args) throws InterruptedException {
        Test3 test3 = new Test3();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test3.load();
            }
        },"threadA").start();
        Thread.sleep(1000);
        new Thread(new Runnable() {
            @Override
            public void run() {
                test3.refresh();
            }
        },"threadB").start();
    }
}

在这里插入图片描述
上图虽然threadB修改了flag=false,但是线程A并没有感知到flag值的变化;结果可以看到,threadA线程没有跳出循环,一致运行着;
那将flag的值的添加volatile关键字之后,看下有什么效果?

public class Test3 {
    private volatile boolean flag = true;

    public void refresh(){
        flag = false;
        System.out.println(Thread.currentThread().getName() + "修改flag");
    }

    public void load(){
        System.out.println(Thread.currentThread().getName() + "开始执行...");
        while (flag){
//            System.out.println(flag);
        }
        System.out.println(Thread.currentThread().getName() + "跳出循环");
    }

    public static void main(String[] args) throws InterruptedException {
        Test3 test3 = new Test3();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test3.load();
            }
        },"threadA").start();
        Thread.sleep(1000);
        new Thread(new Runnable() {
            @Override
            public void run() {
                test3.refresh();
            }
        },"threadB").start();
    }
}

运行结果:
在这里插入图片描述
从结果看:线程B修改flag之后,线程B跳出了循环,从这个例子就验证了volatile的可见性保证。

可见性的原理是如何实现的?

volatile在JMM语义上的保证

java内存模型规定一个变量从读取到写入的过程需要执行8步。
1、lock
2、read 作用于主内存的变量,将主内存的变量传输到线程的工作内存中
3、load 作用于工作内存的变量,将read的变量放入工作内存的变量副本中。
4、use 作用于工作内存的变量副本,把工作内存中的变量传递给执行引擎,每当虚拟机遇到变量值的字节码指令时将会执行这个操作。
5、assign 赋值操作,作用于工作内存的变量,虚拟机遇到对变量赋值字节码指令时执行次操作。
6、store 作用于工作内存的变量,把工作内存的值传输到主内存中,以便随后的write操作
7、write 作用于主内存的变量,它把store操作从工作内存传输的变量写入主内存的变量中
volatile总的原理,能够保证对共享变量的读取,每次都是从主内存中读取;能够保证对共享变量的写入,每次都是写成功后立即将新值刷新到主内存中。
8、unlock

使用volatile修改的变量的read、load、use操作和assign、store、write操作是连续的;即修改后立即将工作内存中的值刷新值主内存,使用时必须从主内存中刷新,由此保证volatile变量的可见性。

volatile在硬件层面上的实现

通过lock前缀指令,会锁定变量缓存行区域并写回主内存,这个操作成为缓存锁定,缓存一致性机制会阻止同时修改被两个以上处理器缓存的内存区域数据,一个处理器的缓存回写到内存会导致其他处理器的缓存失效。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-01-17 11:22:16  更:2022-01-17 11:25:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:58:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码