Java volatile 中 内存屏障是什么

夜敏姑娘_9713

夜敏姑娘_9713

2026-11-11

505人浏览

原创

volatile 变量读写时插入了哪些内存屏障

volatile 关键字在 java 中通过插入特定的内存屏障(memory barrier)来保证可见性和有序性。具体做法是:读操作前插入 loadload 和 loadstore 屏障,写操作后插入 storestore 和 storeload 屏障。这样做会强制 cpu 刷新缓存行到主存并重新加载最新值,同时禁止编译器进行指令重排序。

Java volatile 中 内存屏障是什么

下面是一个验证 volatile 屏障行为的完整程序。它定义了一个共享的 volatile int 变量和一个普通 int 变量,通过线程写入和读取来观察顺序。代码展示了如何触发这些屏障。

public class VolatileBarrierDemo {
    // volatile 变量,触发屏障
    private static volatile int v = 0;
    // 普通变量,无屏障保护
    private static int normal = 0;

    public static void main(String[] args) throws InterruptedException {
        Thread writer = new Thread(() -> {
            normal = 1;      // 步骤 1: 写普通变量
            v = 1;           // 步骤 2: 写 volatile 变量 (触发 StoreStore, StoreLoad)
        });

        Thread reader = new Thread(() -> {
            int r1 = v;        // 步骤 3: 读 volatile 变量 (触发 LoadLoad, LoadStore)
            int r2 = normal;   // 步骤 4: 读普通变量
            System.out.println("r1: " + r1 + ", r2: " + r2);
        });

        writer.start();
        reader.start();
        writer.join();
        reader.join();
    }
}

预期结果:由于 v 的写操作发生在读操作之前,且 volatile 保证了可见性,r1 通常为 1。r2 的值取决于调度,可能为 0 或 1,因为 normal 没有屏障保护,可能与 v 发生重排序。

内存屏障如何防止指令重排序

内存屏障通过限制编译器和处理器的重排序能力来确保代码执行的有序性。对于写操作,StoreStore 屏障确保前面的普通写操作不会被重排序到 volatile 写之后;StoreLoad 屏障确保 volatile 写之后的所有操作不会被重排序到它之前。对于读操作,LoadLoad 屏障确保后面的读操作不会被重排序到 volatile 读之前;LoadStore 屏障确保 volatile 读之后的写操作不会被重排序到它之前。

Java volatile 中 内存屏障是什么

以下代码演示了双重检查锁定(DCL)模式中,如果没有 volatile,指令重排序可能导致实例未完全初始化就被其他线程使用。加入 volatile 后,内存屏障阻止了 new Singleton() 的内部指令与赋值语句的重排序。

Java 开发专家
Java 开发专家

精通 Java 21+,掌握虚拟线程、模式匹配和 Spring Boot 3.x 等现代特性。是 Java 生态系统(包括 GraalVM、Project Lo

下载
public class Singleton {
    // 加上 volatile 防止指令重排序导致的 DCL 失效
    private static volatile Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {          // 第一次检查
            synchronized (Singleton.class) {
                if (instance == null) {  // 第二次检查
                    instance = new Singleton(); // 这里涉及三步:分配内存、初始化、赋值
                    // volatile 写操作插入 StoreStore 和 StoreLoad 屏障
                }
            }
        }
        return instance;
    }
}

预期结果:在多线程环境下,getInstance() 始终返回一个完全初始化的 Singleton 对象。如果没有 volatile,其他线程可能拿到一个引用但对象字段尚未初始化的“半初始化”状态。

volatile 写操作后的 StoreLoad 屏障有什么作用

StoreLoad 屏障是四种屏障中最昂贵的一种,它确保 volatile 写之前的所有内存操作(包括普通读写)都已完成,并且其结果对后续的所有内存操作可见。它主要用于隔离不同的临界区,防止跨临界区的指令重排序。在 x86 架构下,虽然硬件层面通常不执行完整的 StoreLoad 屏障(因为 x86 的强内存模型),但在 Java 内存模型(JMM)层面,它必须被实现,通常通过调用汇编指令或库函数来实现全序一致性。

Java volatile 中 内存屏障是什么

以下代码展示了在并发计数器场景中,volatile 的 StoreLoad 屏障如何确保计数更新的原子性感知。虽然 volatile 本身不保证复合操作的原子性,但它确保了每次写操作对其他线程的即时可见性,配合 StoreLoad 屏障,可以防止后续的读操作读到旧值。

public class Counter {
    private volatile long count = 0;

    public void increment() {
        // 注意:volatile 不保证 i++ 的原子性,这里仅展示屏障效果
        // 实际原子操作应使用 AtomicLong
        long temp = count;
        count = temp + 1; // 写 volatile 变量,触发 StoreLoad 屏障
    }

    public long getCount() {
        return count; // 读 volatile 变量,触发 LoadLoad 屏障
    }
}

预期结果:在单线程下,count 正确递增。在多线程下,getCount() 总是能看到最新的 count 值,尽管 increment() 本身不是原子的,可能存在丢失更新的情况,但可见性是绝对保证的。

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

java

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

12397

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

9482

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

8092

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

1304

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

1048

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1556

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

3249

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

20491

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1415

8

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习