【JAVA进阶篇教学】第十三篇:Java中volatile关键字讲解

博主打算从0-1讲解下java进阶篇教学,今天教学第十三篇:volatile关键字讲解。

在 Java 中,volatile关键字是一种轻量级的同步机制,用于确保变量的可见性和禁止指令重排序。本文将详细解释volatile关键字的工作原理、可见性保证以及与其他锁的相似之处,并通过代码示例进行说明。

目录

一、volatile关键字作用 

二、volatile关键字原理

三、volatile关键字的可见性

四、volatile关键字与锁的相似之处

五、volatile关键字的禁止指令重排序

六、总结


一、volatile关键字作用 

volatile 关键字用于修饰变量,确保多线程环境下对该变量的读写操作是可见的。具体来说,当一个线程修改了 volatile 变量的值时,其他线程能够立即看到这个修改,从而避免了线程之间的数据不一致性问题。

二、volatile关键字原理

volatile 关键字的可见性是通过在编译器和运行时进行一系列优化来实现的。在编译器层面,volatile 变量的读写操作会插入内存屏障指令,确保了线程在进行读写操作时能够从主内存中读取最新的值或将修改后的值刷新到主内存中。在运行时,JVM 会确保对 volatile 变量的操作是原子的,从而保证了多线程环境下的可见性。

注意:volatile并不能保证数据的原子性!

三、volatile关键字的可见性

volatile关键字可以确保变量的可见性。当一个变量被声明为volatile时,它告诉 Java 虚拟机(JVM),这个变量可能会被多个线程同时访问,并且线程对该变量的修改对于其他线程是可见的。

以下是一个简单的示例代码,演示了volatile关键字的可见性:

public class VolatileVisibilityExample {
    private volatile boolean flag = false;

    public void setFlag(boolean value) {
        flag = value;
    }

    public boolean isFlagSet() {
        return flag;
    }

    public static void main(String[] args) {
        VolatileVisibilityExample example = new VolatileVisibilityExample();

        // 创建并启动线程
        Thread thread = new Thread(() -> {
            while (!example.isFlagSet()) {
                // 等待 flag 变为 true
            }
            System.out.println("Flag 已设置为 true");
        });

        thread.start();

        // 修改 flag 的值
        example.setFlag(true);
    }
}

在上述示例中,我们创建了一个名为flag的volatile变量,并在一个线程中不断检查它的值。在主线程中,我们修改了flag的值,并期望子线程能够立即看到这个修改。由于flag是volatile变量,所以线程对flag的修改对于其他线程是可见的,子线程将立即退出循环并输出"Flag 已设置为 true"。

四、volatile关键字与锁的相似之处

  • volatile关键字和锁都可以用于实现线程之间的同步,但它们的实现方式和适用场景有所不同。
  • volatile关键字是一种轻量级的同步机制,它不会引起线程的阻塞和唤醒,因此执行效率较高。但是,volatile关键字只能保证变量的可见性,不能保证原子性。如果需要实现原子性操作,需要使用锁或其他同步机制。
  • 锁是一种更重量级的同步机制,它可以保证原子性、可见性和有序性。锁的实现通常基于操作系统的互斥锁或信号量,因此执行效率较低。但是,锁可以用于实现更复杂的同步逻辑,例如实现临界区、读写锁等。

五、volatile关键字的禁止指令重排序

  • 除了可见性保证之外,volatile关键字还可以禁止指令重排序。指令重排序是一种优化技术,它可以在不改变程序语义的情况下,重新排列指令的执行顺序,以提高执行效率。但是,指令重排序可能会导致多线程程序出现问题,例如竞态条件、数据不一致等。
  • volatile关键字通过添加内存屏障来禁止指令重排序。内存屏障是一种硬件机制,它可以确保在执行当前指令之前,先执行之前的所有内存操作,并且在执行当前指令之后,再执行之后的所有内存操作。这样可以保证指令的执行顺序不会被重排序。

以下是一个简单的示例代码,演示了volatile关键字的禁止指令重排序:

public class VolatileMemoryOrderingExample {
    private volatile int value = 0;

    public void setValue(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }

    public static void main(String[] args) {
        VolatileMemoryOrderingExample example = new VolatileMemoryOrderingExample();

        // 创建并启动线程
        Thread thread = new Thread(() -> {
            int expectedValue = 1;
            while (example.getValue()!= expectedValue) {
                // 等待 value 变为 1
            }
            System.out.println("Value 已设置为 1");
        });

        thread.start();

        // 修改 value 的值
        example.setValue(1);
    }
}

在上述示例中,我们创建了一个名为value的volatile变量,并在一个线程中不断检查它的值。在主线程中,我们修改了value的值,并期望子线程能够立即看到这个修改。由于value是volatile变量,并且使用了内存屏障来禁止指令重排序,所以线程对value的修改对于其他线程是可见的,子线程将立即退出循环并输出"Value 已设置为 1"。

六、总结

volatile关键字是 Java 中的一种轻量级同步机制,它可以确保变量的可见性和禁止指令重排序。volatile关键字适用于多线程环境下的变量共享,例如状态标志、计数器等。与锁相比,volatile关键字的执行效率较高,但不能保证原子性。如果需要实现原子性操作,需要使用锁或其他同步机制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/619094.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

对称加密介绍

一、什么是对称加密 对称密钥算法(Symmetric-key algorithm),又称为对称加密、私钥加密、共享密钥加密,是密码学中的一类加密算法。 对称加密的特点是,在加密和解密时使用相同的密钥,或是使用两个可以简单地相互推算的密钥。 这…

Zynq开发-使用PYNQ快速入门摄像头MIPI驱动(OV5640)-overlay设计

目录 1. 简介 2. Overlay 设计 2.1 总体设计 2.2 MIPI 子系统 2.3 去马赛克 2.4 AXI_IIC 3. 注意事项 4. 总结 1. 简介 本文是关于《Zynq开发-使用PYNQ快速入门摄像头MIPI驱动(OV5640)-CSDN博客》的博客文章,涉及了overlay设计的Vivado工程细节。在使用PYN…

iZotope RX 11 for Mac 激活版:让您的音频焕发生机!

在追求音频完美的道路上,iZotope RX 11 for Mac是您的得力助手。它凭借先进的音频修复技术和丰富的音频增强工具,让您的音频作品焕发出前所未有的生机与活力。无论您是专业的音频工程师,还是业余的音乐爱好者,都能在这款工具中找到…

【Spring】验证 @ServerEndpoint 的类成员变量线程安全

文章目录 前言猜想来源验证方法Controller 的情况ServerEndpoint 的情况 后记 前言 最近有 websocket 的需求。探索 ServerEndpoint 的类成员变量特点。 这里类比 Controller 讨论 ServerEndpoint 类成员变量是否线程安全。 猜想来源 网上的教程大多数都这么展示程序&#…

OBS插件--音频采集

音频采集 音频采集是一款 源 插件,类似于OBS的win-capture/game-capture,允许从特定应用程序捕获音频,而不是捕获整个系统的音频。避免了因为特定音频的采集而需要引入第三方软件,而且时延也非常低。 下面截图演示下操作步骤: 首…

HCIP-Datacom-ARST自选题库_06_排障【28道题】

一、单选题 1.如果面对复杂的网络故障,并经过评估认为短时间内无法完成排障,而此时用户又急需恢复网络的可用性,那么正确的做法是? 告诉用户这是不可能实现的 不通知客户的情况下,直接搭建替代的网络环境 始终尝试排除故障&a…

前端AJAX与后台交互技术知识点及案例(续2)

以下笔记均为学习哔站黑马程序员AJAX视频所得!!! AJAX作用:浏览器和服务器之间通信,动态数据交互 axios函数 先引入axios库,可在bootcdn中寻找相关js文件或者对应的script标签 axios({url:http://hmajax…

最大子矩阵:前缀和、动态规划

最近在学习动态规划,在牛客上刷题时碰到了这一题。其实最初的想法是暴力和前缀和,但是时间复杂度极高,需要套4层循环。后来去网上搜了一下相关的题解和做法,进而了解到了前缀和+线性动态规划的做法。但是在成功做出这题…

【爬虫基础1.1课】——requests模块上

目录索引 requests模块的作用:实例引入: 特殊情况:锦囊1:锦囊2: 这一个栏目,我会给出我从零开始学习爬虫的全过程。感兴趣的小伙伴可以关注一波,用于复习和新学都是不错的选择。 那么废话不多说&#xff0c…

接搭建仿美团、代付系统源码搭建教程

最近很多粉丝催更、分享一下地球号:xiaobao0214520(WX) 现在大家都很流行搞网恋,我们搭建一个跟美团相似的系统 然后开发一个好友代付,我们在点单的时候转发链接让网恋对象付钱 若只是单点外卖的话,能榨出的油水还是太少。 所以…

Redis的数据淘汰策略——Java全栈知识(19)

Redis的数据淘汰策略 什么是数据淘汰策略 数据过期策略是 redis 中设置了 TTL 的数据过期的时候 Redis 的处理策略。数据淘汰策略是 Redis 内存不够的时候, 数据的淘汰策略:当 Redis 中的内存不够用时,此时在向 Redis 中添加新的 key, 那么…

免费思维13招之八:跨行业思维

免费思维13招之八:跨行业思维 免费思维的另一大战略思维——跨行业型思维。 跨行业型思维有两种:一种是通过跨行业,把自己的产品免费掉,从而赚取其他行业的利润。另一种是通过跨行业,把别人的主流产品免费掉,从而增大自己产品的销量。 第一种,把自己的产品免费,从而赚…

ONES 功能上新 | 近期产品新功能一览

支持在 ONES Project 中通过弹窗查看、编辑 ONES Wiki 页面。 应用场景: 当需要在 ONES Project 中查看 ONES Wiki 的页面内容时,可以直接点击工作项关联的 ONES Wiki 页面或项目文档组件中的页面,即可在 ONES Project 中通过弹窗查看 ONES W…

问题解决记录 | 内存溢出

报错截图: 处理方式: 增大PDI工具的内存 打开Spoon.bat配置文件 修改配置

【Linux 网络】网络编程套接字 -- 详解

⚪ 预备知识 1、理解源 IP 地址和目的 IP 地址 举例理解:(唐僧西天取经) 在 IP 数据包头部中 有两个 IP 地址, 分别叫做源 IP 地址 和目的 IP 地址。 如果我们的台式机或者笔记本没有 IP 地址就无法上网,而因为…

与 Apollo 共创生态:Apollo 七周年大会带我体会自动驾驶技术的发展

前言 自动驾驶技术作为当今科技领域的热门话题,吸引着无数开发者和企业的目光。而在这个风起云涌的行业中,Apollo开放平台作为自动驾驶领域的领军者之一,扮演着不可或缺的角色。七年前,当Apollo开放平台刚刚起步时,也…

STM32串口通信入门

文章目录 一、串口协议和RS-232标准,以及RS232电平与TTL电平的区别1.串口通信协议2.RS-232标准3.RS232电平与TTL电平的区别4.USB/TTL转232“模块(CH340芯片为例) 二、补充实验(一)几个常见的库函数、结构体1.时钟配置函…

java入门-面向对象的三大特性

面向对象三大特性 封装 什么是封装 封装 是将代码及其处理的数据绑定在一起的一种编程机制,该机制保证了程序和数据都不受外部干扰且不被误用。 封装的作用 访问控制符 方法传参-值传递 传参类型是基本类型 程序案例: public static void main(St…

Spring Boot 自动装配

本篇主要介绍Spring Boot 自动装配的相关内容。 目录 一、什么是自动装配 二、Bean的扫描方式 ComponentScan Import ImportSelector接口 三、Spring Boot自动装配原理 一、什么是自动装配 在我们在创建Spring Boot项目时往往会根据项目需求,引入很多第三方…

Spring高手之路18——从XML配置角度理解Spring AOP

文章目录 1. Spring AOP与动态代理1.1 Spring AOP和动态代理的关系1.2 AOP基本术语 2. 通过XML配置实现Spring AOP2.1 添加Spring依赖2.2 定义业务接口和实现类2.3 定义切面类2.4 配置XML 1. Spring AOP与动态代理 1.1 Spring AOP和动态代理的关系 Spring AOP使用动态代理作为…