volatile底层原理的再次理解

volatile

volatile作用于变量。能够保证多个线程对该变量修改的可见,一个线程修改了该变量后,另一个线程能够立即感知到。因为volatile修饰的变量存放在主内存中,没有在工作内存中存放副本,变量的读写都是直接操作主内存。什么是主内存和工作内存,看java内存模型(JMM)规定。

JMM java内存模型简述

java内存模型分为两部分:

  • 主内存: 多个线程共享的区域,也就是堆和方法区。主内存存放共享变量。
  • 工作内存:线程的工作内存是线程独有的区域,也就是程序计数器,虚拟机栈,和本地方法栈。工作内存方法共享变量的副本。
    JMM规定线程对变量的读写在工作内存中进行,工作内存中存放了主内存中的一个副本,线程在工作内存中修改了数据后会将数据数据同步到主内存中去,供其他线程读取。但是这过程有时间差,可能导致其他线程读取到的数据不是最新的,导致「可见性」问题。volatile修饰的变量存放在主内存中,不会在工作内存中存放副本。

可见性和有序性保证

变量的可见性: volatile修饰的变量保存在主内存中,不会存放副本在工作内存中,解决了可见性问题

有序性: volatile通过硬件层面的指令屏障,读写屏障来禁止指令排序。在读取数据之前加一个读屏障保证高速缓存中的数据能从主内存中获取最新的数据。在写数据之后,用一个写屏障保证高速缓存中的数据能够及时同步到工作内存中,让其他线程可见。通过读写屏障的配合来保证禁止局部指令的重排,从而保证有序性。

不能保证原子性

不能保证原子性,比如多个线程对一个volatile修饰的变量执行i++操作,最后执行的结果和预期不符合。

java 复制代码
import java.util.concurrent.CountDownLatch;

/**
 * volatile不具有原子性
 * 多个线程i++操作得到的结果和预期不符
 */
public class Volatile {
    private static int cnt;
    public static void add(){
        for (int i = 0; i < 10000; i++) {
            cnt++;
        }
    }

    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(2);// 将执行完的线程阻塞,当计数器为0,线程唤醒
        for (int i = 0; i < 2; i++) {
            new Thread(()->{
                add();
                countDownLatch.countDown();
            }, i+"").start();
        }

        try {
            countDownLatch.await(); // 等待所有线程执行完(计数器为0),线程才会唤醒,否则会一直阻塞
            System.out.println(cnt);// 预计结果是2000
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

参考

一篇文章彻底搞懂volatile关键字底层实现原理

相关推荐
2401_833033626 分钟前
golang如何实现MQTT主题通配符路由_golang MQTT主题通配符路由实现策略
jvm·数据库·python
m0_5967490928 分钟前
Golang怎么实现方法集与接口的匹配_Golang如何理解值类型和指针类型实现接口的区别【详解】
jvm·数据库·python
我是无敌小恐龙1 小时前
Java基础入门Day10 | Object类、包装类、大数/日期类、冒泡排序与Arrays工具类 超详细总结
java·开发语言·数据结构·算法·贪心算法·排序算法·动态规划
极客先躯1 小时前
高级java每日一道面试题-2025年12月07日-实战篇[Dockerj]-Docker daemon 的配置文件在哪里?常用的配置项有哪些?
java·docker·配置文件的实际位置·配置文件的格式规则·常用配置项全景与分类·配置如何生效·daemon 配置折射架构思维
云烟成雨TD1 小时前
Spring AI Alibaba 1.x 系列【49】状态图运行时引擎:CompiledGraph 源码解析
java·人工智能·spring
Tutankaaa1 小时前
从10队到50队:知识竞赛软件的高并发场景如何设计?
java·经验分享·后端·spring
下次再写2 小时前
微服务架构实战:Spring Boot + Spring Cloud 从入门到精通
java·spring boot·spring cloud·微服务架构·服务注册与发现·分布式系统·api网关
bang冰冰2 小时前
Trae工具安装和使用教程(新手零基础入门,全程无坑)
java·人工智能·python
阿丰资源2 小时前
基于Spring Boot的网上摄影工作室系统(源码一键运行)
java·spring boot·后端
阿维的博客日记2 小时前
容器是怎么管理 Bean 的?
java·bean