volatile

volatile: 用来声明变量的关键字之一,它的主要作用是确保多个线程能够正确地处理共享变量。在多线程编程中,如果一个变量被多个线程共享并且这些线程可能同时修改该变量的值,那么就需要使用 volatile 关键字来保证线程之间对该变量的操作是可见的、有序的。

特点:

1、可见性(Visibility)

当一个变量被 volatile 关键字修饰时,如果一个线程修改了这个变量的值,那么其他线程将立即看到这个修改。这是因为 volatile 会告诉 JVM 不要将该变量缓存在线程的工作内存中,而是直接从主内存中读取和写入变量的值。

1.JMM(Java Memory Model)

一种规范,用于定义 Java 程序中多线程并发访问共享内存时的行为。JMM 主要关注的是多线程之间如何访问共享变量以及如何同步它们的访问。
在这里插入图片描述
线程工作内存是拷贝系统主内存的数据,然后对于数据操作,写入线程。当一方改变主内存数据时,另一方不可见。
八种指令操作
lock(锁定): 作用于主内存的变量,它把一个变量标识为一条线程独占的状态;
unlock(解锁): 作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定;
read(读取): 作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便随后的load动作使用;
load(载入): 作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中;
use(使用): 作用于工作内存的变量,它把工作内存中一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用变量的值的字节码指令时将会执行这个操作;
assign(赋值): 作用于工作内存的变量,它把一个从执行引擎接收的值赋给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作;
store(存储): 作用于工作内存的变量,它把工作内存中一个变量的值传送到主内存中,以便随后的write操作使用;
write(写入): 作用于主内存的变量,它把store操作从工作内存中得到的变量的值放入主内存的变量中;

2.代码展示

//当我们不加volatile,程序就不会结束,主线程修改主内存数据,不会通知线程a
private static volatile int a = 0;
public static void main(String[] args) {
   new Thread(()->{
       while (a == 0){

       }
   },"a").start();
   try {
       TimeUnit.SECONDS.sleep(2);
   } catch (InterruptedException e) {
       throw new RuntimeException(e);
   }

   a = 1;
   System.out.println("q =>" + a);
}

2.不能保证原子性

原子性是指一个操作是不可分割的,要么全部执行成功,要么全部不执行,不存在中间状态。在并发编程中,原子性是保证多线程并发操作共享变量时的一个重要特性。

1.代码示例

//volatile不保证原子性
private volatile static int a = 0;
private static Lock lock = new ReentrantLock();
//synchronized lock 可以保证原子性
public static void add() {
    lock.lock();
    try {
        a++;
    }catch (Exception e){

    }finally {
        lock.unlock();
    }

}
public static void main(String[] args) {
    for (int i = 1; i <= 20; i++) {
        new Thread(()->{
            for (int j=0;j<1000;j++){
                add();
            }
        }).start();
    }

    //上面线程执行完执行主线程
    while (Thread.activeCount() > 2){
        Thread.yield();
    }
    //输出结果期待值是2W
    System.out.println("a=>" + a);
}

2.并发编程保证原子性操作

1.synchronized 关键字: 使用 synchronized 关键字可以保证某个代码块或方法在同一时刻只能被一个线程执行,从而确保了对共享资源的原子性访问。

public static synchronized void add() {
    a++;
}

2.Lock 接口: 使用 Lock 接口及其实现类(如 ReentrantLock)也可以实现对共享资源的原子性访问。

public static void add() {
    lock.lock();
    try {
        a++;
    }catch (Exception e){
        
    }finally {
        lock.unlock();
    }
    
}

3.原子类(Atomic Classes): Java 并发包中提供了一系列原子类,如 AtomicInteger、AtomicLong 等,它们提供了一种线程安全的方式来更新共享变量的值,保证了原子性操作。

private static AtomicInteger a = new AtomicInteger();
public static void add(){
    a.getAndIncrement();
}
public static void main(String[] args) {
    for (int i = 1; i <= 20; i++) {
        new Thread(()->{
            for (int j=0;j<1000;j++){
                add();
            }
        }).start();
    }

    //上面线程执行完执行主线程
    while (Thread.activeCount() > 2){
        Thread.yield();
    }
    //输出结果期待值是2W
    System.out.println("a=>" + a);
}

3.禁止指令重排序(Preventing Instruction Reordering)

关键字还可以禁止 JVM 对指令进行重排序优化,保证指令执行顺序与程序中的代码顺序一致。这样可以避免由于指令重排序导致的线程安全问题。
1.编译器优化重排序: 编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。
2.指令级并行的重排序: 现代处理器采用了指令级并行技术(Instruction-Level Parallelism, ILP)来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。
3.内存系统的重排序: 处理器使用缓存和读写缓冲区,这使得加载和存储操作看上去可能是在乱序执行(强调的是内存缓存)。
在这里插入图片描述

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

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

相关文章

IPV6——缓解地址池枯竭

目录 一.IPV6的来源 二.关于IPV6 1.’无限‘的地址空间 2.简化报文头部 3.层次化结构设计 4.即插即用 5.安全特性 6.Qos特性 三.IP v4&#xff0c;IP v6报文头部 IP v4 重点—TTL&#xff08;Time to live&#xff09; —— 存活时间&#xff0c;用于三层防环&#…

二维码电子画册制作教程,教你如何做出高端作品!

当今社会&#xff0c;二维码已经成为了信息传递的重要方式之一&#xff0c;其在电子商务、广告营销、活动推广等领域广泛应用。而如何将二维码巧妙地融入电子画册中&#xff0c;制作出高端、具有吸引力的作品&#xff0c;成为了许多设计师和营销人员关注的焦点 但是很多人却不知…

K8s的亲和、反亲和、污点、容忍

1 亲和与反亲和 亲和性的原理其实很简单&#xff0c;主要利用label标签结合nodeSelector选择器来实现 1.1 Pod和Node 从pod出发&#xff0c;可以分成亲和性和反亲和性&#xff0c;分别对应podAffinity和podAntiAffinity。从node出发&#xff0c;也可以分成亲和性和反亲和性&…

FANUC机器人通过ROBOGUIDE实现与实际的机器人进行程序导入导出的具体方法示例

FANUC机器人通过ROBOGUIDE实现与实际的机器人进行程序导入导出的具体方法示例 如下图所示,在电脑的开始菜单中找到”Robot Neiborhood”,点击进入, 如下图所示,设置要连接的机器人名称和主机IP地址(要确保自己的电脑和机器人IP地址在同一网段内),点击Add添加, 添加在线…

[Qt网络编程]之获取基本网络信息

前言 获取主机的网络地址和接口信息是进行网络编程的第一步&#xff0c;也是网络编程的基础。Qt提供了网络接口类 QNetworkInterface、网络地址人口类 QNetworkAddressEntry 和主机地址类 QHostAddress 来获取和使用地址信息。其中网络接口类 QNetworkInterface 描述了主机的卫…

光电水位开关数字信号与模拟信号的区别

如今随着液位检测技术的不断发展&#xff0c;检测液位的方法也越来越多&#xff0c;在小家电领域应用最多的液位检测方法就是光电液位传感器&#xff0c;光电液位传感器分为数字信号和模拟信号两种&#xff0c;都是输出高低电压信号&#xff0c;但输出的电压不一样。 数字信号…

OJ 连续数的和 球弹跳高度的计算【C判断是否为完全平方数】【格式输出%g输出全部小数部分】

连续数的和 判断是否为完全平方数有两种方法 1.遍历所有小于该数的整数&#xff0c;有一个满足平方与该数相等&#xff0c;则是完全平方数 2.用sqrt()或pow()函数对该数开方&#xff0c;取整&#xff08;舍去小数部分&#xff09;&#xff0c;再平方&#xff0c;与该数相等则…

项目7-音乐播放器4

1.喜欢/收藏音乐模块设计 1.1 请求响应模块设计 请求&#xff1a; { post, /lovemusic/likeMusic data: id//音乐id } 响应&#xff1a; { "status": 0, "message": "点赞音乐成功", "da…

力扣:120. 三角形最小路径和

力扣&#xff1a;120. 三角形最小路径和 给定一个三角形 triangle &#xff0c;找出自顶向下的最小路径和。 每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 1 的两个结点。也就是说&#xff0c;如果正…

特殊文件-XML文件

简介 XML全称&#xff1a;Etensible Markup Language&#xff0c;可扩展标记语言 特点 标签都是成对出现的&#xff0c;一个标签就是一个元素一个xml文件中有且只有一个根标签标签也是可以携带属性的 IDEA创建XML 简单示例 必须有抬头标签是可以携带属性的&#xff0c;但是属性…

c++程序员简历中项目怎么写?避免踩坑!

C开发 9 年&#xff0c;目前人在大厂&#xff0c;做 C 相关的开发&#xff0c;作为资深 C 面试官&#xff0c;我来聊聊面试官眼中的校招简历中的 C 项目吧&#xff0c;希望对各位学弟学妹有帮助。 1. 简历中如何介绍自己的项目&#xff1f; 从面试官的角度来说&#xff0c;我…

QAnything部署Mac m1环境

本次安装时Qanything已经更新到了v1.3.3&#xff0c;支持纯python安装。安装过程比较简单&#xff0c;如下&#xff1a; QAnything/README_zh.md at qanything-python-v1.3.1 netease-youdao/QAnything GitHub 首先需要用Anaconda3创建隔离环境&#xff0c;简要说明下Anaco…

中型企业用CRM管理软件,求推荐?

中型企业是指哪些企业呢&#xff1f; 指的是员工人数在数百至数千人之间&#xff0c;年营业额在几千万至数亿元之间的企业。这些企业通常已经形成了较为稳定的业务模式和市场定位&#xff0c;有一定的市场份额和客户基础&#xff0c;同时也在积极拓展新的业务领域和市场空间。…

工业控制(ICS)---OMRON

OMRON FINS 欧姆龙厂商 命令代码(Command CODE)特别多&#xff0c;主要关注读写相关&#xff0c;如&#xff1a; Memory Area Read (0x0101) Memory Area Write (0x0102) Multiple Memory Area Read (0x0104) Memory Area Transfer (0x0105) Parameter Area Read (0x0201) Pa…

搜维尔科技:【工业仿真】煤矿安全知识基础学习VR系统

产品概述 煤矿安全知识基础学习VR系统 系统内容&#xff1a; 煤矿安全知识基础学习VR系统内容包括&#xff1a;下井流程&#xff08;正确乘坐罐笼、班前会、井下行走注意事项、工作服穿戴、入井检身及人员清点、下井前准备工作、提升运输安全&#xff09;&#xff1b;运煤流程…

Windows平台RTMP推送|轻量级RTSP服务如何实现摄像头叠加到屏幕输出

技术背景 我们在用Windows平台RTMP推送、轻量级RTSP服务实现无纸化同屏、智慧教室等场景的时候&#xff0c;有个需求是&#xff0c;需要主讲人&#xff08;或老师&#xff09;的摄像头数据&#xff0c;叠加到屏幕上输出出去&#xff0c;这就是今天我们需要讲的视频视频叠加。 …

appium2报错:Failed to create session. ‘automationName‘ can‘t be blank

1、问题概述&#xff1f; 今天在window环境中安装了appium2.5.2版本&#xff0c;通过appium inspector连接真机的时候报错如下&#xff1a; Failed to create session. automationName cant be blank 原因分析&#xff1a;这是因为appium2的比appium1有了很大的改进&#xff…

C++ 类和对象(二)

目录 1.前言 2.类的六个默认成员函数 3.构造函数 3.1概念 3.2特性 3.2.1 函数名与类名相同 3.2.2 无返回值 3.2.3对象实例化时自动调用 3.2.4 构造函数可以重载 3.2.5 默认构造函数的自动生成 3.2.6 默认构造函数对内置类型成员的初始化 3.2.7 默认构造函数的定义 4…

小红书app缓存清除

1.背景 小伙伴们&#xff0c;手机app运行产生的缓存在不断侵占着我们的收集的内存&#xff0c;运行个半年发现内存不足20%。其实很多情况我们通过各个手机自带的缓存清除功能&#xff0c;就可以把app运行过程中产生的内存清除掉&#xff0c;节省我们不少的空间。想一想手机上a…

二分查找的时间复杂度的讲解

二分查找的代码&#xff1a; 二分查找的时间复杂度&#xff1a; 最坏的情况&#xff1a; 就是找不到和查找区间只剩一个值的时候&#xff0c;这两种都是最坏的结果&#xff0c;假设查找了x次&#xff0c;达到了最坏的结果&#xff1a; N代表每一次折半区间数据的个数&#xf…