博客
关于我
并发编程——Volatile原理
阅读量:797 次
发布时间: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/

    你可能感兴趣的文章
    MYSQL中TINYINT的取值范围
    查看>>
    MySQL中UPDATE语句的神奇技巧,让你操作数据库如虎添翼!
    查看>>
    Mysql中varchar类型数字排序不对踩坑记录
    查看>>
    MySQL中一条SQL语句到底是如何执行的呢?
    查看>>
    MySQL中你必须知道的10件事,1.5万字!
    查看>>
    MySQL中使用IN()查询到底走不走索引?
    查看>>
    Mysql中使用存储过程插入decimal和时间数据递增的模拟数据
    查看>>
    MySql中关于geometry类型的数据_空的时候如何插入处理_需用null_空字符串插入会报错_Cannot get geometry object from dat---MySql工作笔记003
    查看>>
    mysql中出现Incorrect DECIMAL value: '0' for column '' at row -1错误解决方案
    查看>>
    mysql中出现Unit mysql.service could not be found 的解决方法
    查看>>
    mysql中出现update-alternatives: 错误: 候选项路径 /etc/mysql/mysql.cnf 不存在 dpkg: 处理软件包 mysql-server-8.0的解决方法(全)
    查看>>
    Mysql中各类锁的机制图文详细解析(全)
    查看>>
    MySQL中地理位置数据扩展geometry的使用心得
    查看>>
    Mysql中存储引擎简介、修改、查询、选择
    查看>>
    Mysql中存储过程、存储函数、自定义函数、变量、流程控制语句、光标/游标、定义条件和处理程序的使用示例
    查看>>
    mysql中实现rownum,对结果进行排序
    查看>>
    mysql中对于数据库的基本操作
    查看>>
    Mysql中常用函数的使用示例
    查看>>
    MySql中怎样使用case-when实现判断查询结果返回
    查看>>
    Mysql中怎样使用update更新某列的数据减去指定值
    查看>>