博客
关于我
并发编程——Volatile原理
阅读量:799 次
发布时间:2023-03-28

本文共 1565 字,大约阅读时间需要 5 分钟。

Volatile关键字深度解析:可见性与非原子性的权衡

JMM内存模型:理解Java内存管理的核心

在Java编程中,内存模型是Java Virtual Machine (JVM) 规范中定义的核心概念。它屏蔽了底层计算机的差异,为程序提供了一致的内存抽象。现代计算机系统为了提高性能,引入了高速缓存(cache),将内存与处理器之间作为缓冲层。这种设计虽然提高了性能,但也带来了缓存一致性(Cache Coherence)的复杂性。

在多处理器系统中,每个处理器都有自己的缓存,而所有处理器共享同一主内存。Java内存模型(JavaMemoryModel)定义了共享变量的访问规则。所有共享变量(如实例变量和类变量)存储在主内存中,而线程有自己的工作内存,用于存储被线程使用的变量副本。线程对变量的读写操作必须在工作内存完成,线程间变量的传递需要通过主内存完成。

Volatile的可见性原理:保证线程间数据一致性

Volatile关键字通过两个关键特性确保线程间的可见性和有序性:

  • 读取和写入的连续性

    • 在读操作(load)之前,必须先执行读操作(read)。
    • 在写操作(write)之后,必须执行写操作(store)。

    这种连续性保证了工作内存在读取前必须刷新主存的最新值,写入后必须同步到主存。

  • 禁止指令重排:Volatile插入内存屏障,阻止编译器对指令进行重排优化。这样可以防止缓存层面上的数据不一致问题。

  • Volatile的非原子性:理解其局限性

    尽管Volatile保证了可见性和有序性,但它本身并不提供原子性操作。由于非原子性,以下操作可能导致数据竞争:

  • use和assign的非连续性

    • 主存读取num的值。
    • 执行num++运算。
    • 将num值写入主存。

    如果多个线程同时进行这些操作,可能导致脏数据的读写不一致。

  • 线程安全的适用范围

    • 当运算结果不依赖于变量的状态或不依赖于其他状态变量时。
    • 当变量的值传递不受其他操作的影响时。
  • Volatile与Synchronized的配合使用:双重保障

    在需要更高级别的线程安全时,Volatile通常与Synchronized结合使用。Synchronized通过获取对象锁,确保代码块串行执行,并禁止指令重排,从而保证线程安全。

    例如,在单例模式中,双检查锁(Double Checked Locking)结合Volatile可以有效防止多线程实例化过程中的竞态条件:

    public class Singleton {    private volatile static Singleton instance = null;    private Singleton() {}    public static Singleton getInstance() {        if (instance == null) {            synchronized (Singleton.class) {                if (instance == null) {                    instance = new Singleton();                }            }        }        return instance;    }}

    这种设计通过Volatile防止指令重排,确保单例实例化的正确性。

    总结

    Volatile是Java中一个强大的工具,但其可见性和有序性并不意味着原子性。正确使用Volatile需要结合上下文,特别是在涉及线程安全时,通常需要与Synchronized配合。理解Volatile的特性和局限性,对于实现高效且线程安全的Java程序至关重要。

    转载地址:http://dlhfk.baihongyu.com/

    你可能感兴趣的文章
    SpringBoot中集成海康威视SDK实现布防报警数据上传/交通违章图片上传并在linux上部署(附示例代码资源)
    查看>>
    POSIX标准和XSI扩展
    查看>>
    post install error,please remove node_moules before retry
    查看>>
    postcss-pxtorem 参数之selectorBlackList、exclude的用法
    查看>>
    Postek博思得标签打印机更换电脑,打印出来标签空白
    查看>>
    postfix+ dovecot搭建邮件服务器
    查看>>
    postfix在邮件服务器中的使用
    查看>>
    PostGIS 3.1.2软件安装详细教程(地图工具篇.8)
    查看>>
    PostGIS中获取所有EPSG的编码以及对应Proj4字符串
    查看>>
    SpringBoot中集成海康威视SDK实现布防报警数据上传/交通违章图片上传并在linux上部署(附示例代码资源)
    查看>>
    PostGIS在Windows上的下载与安装
    查看>>
    Qt开发——网络编程之UDP客户端
    查看>>
    postgis数据库优化_postgresql 性能优化
    查看>>
    postgis求面积、交集等相关函数
    查看>>
    postgis相关函数
    查看>>
    Postgres Docker版本安装mysql_fdw 插件
    查看>>
    Postgres invalid command \N数据恢复处理
    查看>>
    Postgres like 模糊查询匹配集合
    查看>>
    Postgres 自定义函数内实现 in 操作符的递归查询
    查看>>
    Postgres 返回当前时间前后指定天数的集合
    查看>>