当前位置: 首页 > news >正文

Java volatile学习

面试题:
1、请谈谈你对volatile的理解?
volatile是Java虚拟机提供的轻量级的同步机制1.保证可见性2.不保证原子性3.禁止指令重排
2、JMM你谈谈?Java内存模型 
3、你在哪些地方用到过volatile?单例模式CAS底层代码

目录

一、概述

 1、可见性

2、原子性

3、有序性

4、总结


一、概述

        JMM(Java内存模型 Java Memory Model,简称JMM) 本身是一种抽象的概念并不真实存在,它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构造数组对象的元素)的访问方式。

JMM关于同步的规定:

1、线程解锁前,必须把共享变量的值刷新回主内存

2、线程加锁前,必须读取主内存的最新值到自己的工作内存

3、加锁解锁是同一把锁

主内存:内存8G硬件内存条
自己的工作内存:各自线程的工作内存工作速率:硬盘<内存<CPU
CPU与内存之间读取有一个缓存cache;
CPU计算数据计算完,但是内存数据还没拿到,此时CPU干等着?CPU和内存之间有一个缓存来临时存储数据。
可以通过CPU-Z软件来查看,有一个缓存工具栏。

        由于JVM运行程序的实体是线程,而每个线程创建时JVM都会为其创建一个工作内存(有些地方称为栈空间),工作内存是每个线程的私有数据区域,而Java内存模型中规定所有变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问,但线程对变量的操作(读取赋值等)必须在工作内存中进行,首先要将变量从主内存拷贝到自己的工作内存空间,然后对变量进行操作,操作完成后再将变量写回主内存,不能直接操作主内存中的变量,各个线程中的工作内存中存储着主内存中的变量副本拷贝,因此不同的线程间无法访问对方的工作内存,线程间的通信(传值)必须通过主内存来完成,其简要访问过程如下图:

 1、可见性

这种第一时间通知内存修改的消息机制,就叫Java内存模型中的可见性。可以理解为及时通知。

可见性的代码验证

import java.util.concurrent.TimeUnit;public class VolatileDemo {public static void main(String[] args) {MyData myData = new MyData();new Thread(() -> {System.out.println(Thread.currentThread().getName() + "\t in");try {TimeUnit.SECONDS.sleep(3);} catch (Exception e) {e.printStackTrace();}myData.add();System.out.println(Thread.currentThread().getName() + "\t over ,num=" + myData.num);}, "aa").start();while (myData.num == 0) {// main线程一直在此等待,直到num不等于0}System.out.println(Thread.currentThread().getName() + "\t over");}}class MyData {int num = 0;public void add() {this.num = 60;}
}

结果如下并且main线程一直没结束,没人通知它num值变更了。

aa     in
aa     over ,num=60

修改程序,增加volatile:

import java.util.concurrent.TimeUnit;public class VolatileDemo {public static void main(String[] args) {MyData myData = new MyData();new Thread(() -> {System.out.println(Thread.currentThread().getName() + "\t in");try {TimeUnit.SECONDS.sleep(3);} catch (Exception e) {e.printStackTrace();}myData.add();System.out.println(Thread.currentThread().getName() + "\t over ,num=" + myData.num);}, "aa").start();while (myData.num == 0) {// main线程一直在此等待,直到num不等于0}System.out.println(Thread.currentThread().getName() + "\t over ,num=" + myData.num);}}class MyData {volatile int num = 0;public void add() {this.num = 60;}
}

此时结果:

aa	 in
aa	 over ,num=60
main	 over ,num=60

线程aa中把num值变更了,及时通知主线程main,此为JMM的可见性。

通过前面对JMM介绍,我们知道各个线程对主内存中共享变量的操作都是各个线程各自拷贝到自己的工作内存进行操作后再写回到主内存中的。

这就可能存在一个线程aa修改了共享变量X的值还未写回主内存时,另外一个线程bb又对主内存中同一个共享变量X进行操作,但此时aa线程工作内存中的共享变量X对bb来说并不可见,这种工作内存与主内存同步延迟现象就造成了可见性问题

2、原子性

2.1、原子性指的是什么意思?

不可分割,完整性,也即某个线程正在做某个具体业务时,中间不可以被加塞或者被分割,需要整体完善要么同时成功,要么同时失败。

2.2、volatile不保证原子性

验证不保证原子性

public class VolatileDemo {public static void main(String[] args) {MyData myData = new MyData();for (int i = 1; i <= 20; i++) {new Thread(() -> {for (int j = 1; j <= 1000; j++) {myData.addPlus();}}, String.valueOf(i)).start();}while (Thread.activeCount() > 2) {Thread.yield();}// 上面20个线程计算完最终结果System.out.println(Thread.currentThread().getName() + "\t num=" + myData.num);}}class MyData {volatile int num = 0;public void add() {this.num = 60;}public void addPlus() {this.num++;}
}

结果:main     num=16919       每一次运行结果都不一致。

2.3、如何解决原子性?

        1、加synchronized

        2、使用JUC下的AtomicInteger解决

import java.util.concurrent.atomic.AtomicInteger;public class VolatileDemo {public static void main(String[] args) {MyData myData = new MyData();for (int i = 1; i <= 20; i++) {new Thread(() -> {for (int j = 1; j <= 1000; j++) {myData.addPlus();myData.addAtomic();}}, String.valueOf(i)).start();}while (Thread.activeCount() > 2) {Thread.yield();}// 上面20个线程计算完最终结果System.out.println(Thread.currentThread().getName() + "\t num=" + myData.num);System.out.println(Thread.currentThread().getName() + "\t atomicInteger=" + myData.atomicInteger);}}class MyData {volatile int num = 0;public void add() {this.num = 60;}public synchronized void addPlus() {this.num++;}AtomicInteger atomicInteger = new AtomicInteger();public void addAtomic() {atomicInteger.getAndIncrement();}}

结果:

main     num=20000
main     atomicInteger=20000

3、有序性

计算机在执行程序时,为了提高性能,编译器和处理器常常会对指令做重排,一般分以下3种。

源代码-->编译器优化的重排-->指令并行的重排-->内存系统的重排-->最终执行的指令

单线程环境里面确保程序最终执行结果和代码顺序执行的结果一致。

处理器在进行重排序时必须要考虑指令之间的数据依赖性

多线程环境中线程交替执行,由于编译器优化重排的存在,两个线程中使用的变量能否保证一致性是无法确定的,结果无法预测。

public class ReSortSeqDemo {int a = 0;boolean flg = false;public void m1() {a = 1;flg = true;}// 多线程环境中线程交替执行,由于编译器优化重排的存在,// 两个线程中使用的变量能否保证一致性是无法确定的,结果无法预测。
// m1方法中的a=1和flg=true;的执行顺序因为有编译器重排的存在,有可能flg=true先执行,后执行a=1;// flg=true先执行时,突然m2方法线程执行,此时a=0+5;否则有可能a=1+5;public void m2() {if (flg) {a = a + 5;}}}

4、总结

        volatile实现禁止指令重排优化,从而避免多线程环境下程序出现乱序执行的现象

先了解一个概念,内存屏障(Memory Barrier)又称内存栅栏,是一个CPU指令,它的作用有两个:

一是保证特定操作的执行顺序。

二是保证某些变量的内存可见性(利用该特性实现volatile的内存可见性)

        由于编译器和处理器都能执行指令重排优化。如果在指令间插入一条Memory Barrier则会告诉编译器和CPU,不管什么指令都不能和这条Memory Barrier指令重排序,也就是说通过插入内存屏障禁止在内存屏障前后的指令重排序优化。内存屏障另外一个作用是强制刷出各种CPU的缓存数据,因此任何CPU上的线程都能读取到这些数据的最新版本。

        对volatile变量进行写操作时,会在写操作后加入一条store屏障指令,将工作内存中的共享变量值刷新回主内存。

        对volatile变量进行读操作时,会在读操作前加入一条load屏障指令,从主内存中读取共享变量。

volatile可应用在单例模式下

单例模式

干我们这行,啥时候懈怠,就意味着长进的停止,长进的停止就意味着被淘汰,只能往前冲,直到凤凰涅槃的一天!

相关文章:

Java volatile学习

面试题&#xff1a; 1、请谈谈你对volatile的理解&#xff1f; volatile是Java虚拟机提供的轻量级的同步机制1.保证可见性2.不保证原子性3.禁止指令重排 2、JMM你谈谈?Java内存模型 3、你在哪些地方用到过volatile?单例模式CAS底层代码 目录 一、概述 1、可见性 2、原子性…...

用神经网络分类上和下

( A, B )---3*30*2---( 1, 0 )( 0, 1 ) 做一个网络&#xff0c;输入为3个点&#xff0c;训练集A,B各有4张图片。让B的4张图片全是0.排列组合A&#xff0c;记录迭代次数平均值的变化。收敛误差为7e-4&#xff0c;每个网络收敛199次。 其中得到一组数据 差值结构 1-A-B 迭代次…...

VS Code 1.75 发布!

欢迎使用 2023 年 1 月版的 Visual Studio Code。希望您喜欢此版本中的许多更新&#xff0c;其中一些主要亮点包括&#xff1a;配置文件、VS Marketplace 签名、辅助功能改进、更轻松地调整多视图大小、树视图搜索历史、新的 Git 命令等等。让我们一起看看吧&#xff01; 配置文…...

Vue2仿网易云风格音乐播放器(附源码)

Vue2仿网易云风格音乐播放器1、整体效果2、使用技术3、实现内容4、源码5、使用图片1、整体效果 2、使用技术 使用了HTML5 CSS3进行页面布局及美化使用Vue2进行数据渲染与页面交互使用Axios发送http请求获取数据 3、实现内容 实现了搜索歌曲功能&#xff0c;输入歌手或歌曲关…...

Spring相关面试题

文章目录请谈一下你对 spring 的理解&#xff1f;说一下 Spring 的核心是什么&#xff1f;请谈 一下你对 Spring IOC 和 和 AOP 的理解&#xff1f;请说一下 Spring 的 的 Bean 作用域&#xff1f;请谈一下Spring中bean对象的生命周期&#xff1f;Spring中的事务是如何实现的 &…...

操作符详解(上篇)

前言小伙伴们大家好&#xff0c;随着对c的不断学习今天我们将来学习操作符。在初始c语言中也介绍过操作符但也只是点到即可&#xff0c;今天我们将详细了解操作符。操作符分类&#xff1a;算术操作符移位操作符位操作符赋值操作符单目操作符关系操作符逻辑操作符条件操作符逗号…...

采样电路的3个组成部分

采样电路的使用实际上是电路的一个闭环控制过程&#xff0c;也可以理解为一个负反馈过程&#xff0c;采集的信号被传送到主控制芯片进行调整。今天就来为您介绍一下采样电路的三个组成部分分析&#xff01;一起来看看吧&#xff01; 这里的采样实际上分为电流采样、电压采样、…...

ffmpeg硬解码与软解码的压测对比

文章目录ffmpeg硬解码与软解码的压测一、基本知识二、压测实验1. 实验条件及工具说明2. 压测脚本3. 实验数据结果ffmpeg硬解码与软解码的压测 一、基本知识 本文基于intel集显进行压测 软解码&#xff1a;cpu对视频进行解码硬解码&#xff1a;显卡或者多媒体处理芯片对视频进…...

操作符——“C”

各位CSDN的uu们你们好呀&#xff0c;今天&#xff0c;总算是要到我们的操作符啦&#xff0c;在C语言中&#xff0c;操作符是一个极为复杂的东西&#xff0c;下面&#xff0c;就让我们进入操作符的世界吧 算术操作符 移位操作符 位操作符 赋值操作符 单目操作符 关系操作符…...

YSP的UI界面设计

文章目录一、准备工作二、UI设计1.QPushButton&#xff1a;三、遇到的bug一、准备工作 1.MSVC和MinGW上编译的项目&#xff0c;不能用另一个编译器进行编译 2.若要使用MSVC编译器&#xff0c;需要下载对应版本的VS 见此篇&#xff1a;https://blog.csdn.net/Copperxcx/article…...

干货 | 什么是磁传感器?最常用的磁传感器类型及应用

1、什么是磁传感器&#xff1f;磁传感器通常是指将磁场的大小和变化转换成电信号。磁场&#xff0c;以地球磁场(地磁)或磁石为例的磁场是我们熟悉但不可见的现象。将不可见的磁场转化为电信号&#xff0c;以及转化为可见效应的磁传感器一直以来都是研究的主题。从几十年前使用电…...

操作符(运算符)详解

&#x1f680;&#x1f680;&#x1f680;大家觉不错的话&#xff0c;就恳求大家点点关注&#xff0c;点点小爱心&#xff0c;指点指点&#x1f680;&#x1f680;&#x1f680; 目录 &#x1f430;算数操作符&#xff1a; - * / % &#x1f430;移位操作符&#x…...

【LeetCode每日一题】【2023/2/9】1797. 设计一个验证系统

文章目录1797. 设计一个验证系统方法1&#xff1a;哈希表代码总体1797. 设计一个验证系统 LeetCode: 1797. 设计一个验证系统 中等\color{#FFB800}{中等}中等 你需要设计一个包含验证码的验证系统。每一次验证中&#xff0c;用户会收到一个新的验证码&#xff0c;这个验证码在…...

计算机图形学:改进的中点BH算法

作者&#xff1a;非妃是公主 专栏&#xff1a;《计算机图形学》 博客地址&#xff1a;https://blog.csdn.net/myf_666 个性签&#xff1a;顺境不惰&#xff0c;逆境不馁&#xff0c;以心制境&#xff0c;万事可成。——曾国藩 文章目录专栏推荐专栏系列文章序一、改进缘由二、…...

【SQL开发实战技巧】系列(六):从执行计划看NOT IN、NOT EXISTS 和 LEFT JOIN效率,记住内外关联条件不要乱放

系列文章目录 【SQL开发实战技巧】系列&#xff08;一&#xff09;:关于SQL不得不说的那些事 【SQL开发实战技巧】系列&#xff08;二&#xff09;&#xff1a;简单单表查询 【SQL开发实战技巧】系列&#xff08;三&#xff09;&#xff1a;SQL排序的那些事 【SQL开发实战技巧…...

十分钟利用环信WebIM-vue3-Demo,打包上线一个即时通讯项目【含音视频通话】

这篇文章无废话&#xff0c;只教你如果接到即时通讯功能需求&#xff0c;十分钟利用环信WebIM-vue3-Demo&#xff0c;打包上线一个即时通讯项目【包含音视频通话功能】。 写这篇文章是因为&#xff0c;结合自身情况&#xff0c;以及所遇到的有同样情况的开发者在接到即时通讯&a…...

pandas——DataFrame基本操作(二)【建议收藏】

pandas——DataFrame基本操作&#xff08;二&#xff09; 文章目录pandas——DataFrame基本操作&#xff08;二&#xff09;一、实验目的二、实验原理三、实验环境四、实验内容五、实验步骤1.修改数据2.缺失值3.合并1.concat合并2.使用append方法合并3.使用merge进行合并4.使用…...

PostgreSQL查询引擎——General Expressions Grammar之restricted expression

General expressions语法规则定义在src/backend/parser/gram.y文件中&#xff0c;其是表达式语法的核心。有两种表达式类型&#xff1a;a_expr是不受限制的类型&#xff0c;b_expr是必须在某些地方使用的子集&#xff0c;以避免移位/减少冲突。例如&#xff0c;我们不能将BETWE…...

从某种程度上来看,产业互联网是一次对于互联网的弥补和修正

如果对当下我们正在经历的这样一个时代进行一次定义的话&#xff0c;我更加愿意将其划归到产业互联网的范畴里。可能有人会说&#xff0c;这与产业互联网并无联系&#xff0c;因为从本质上来看&#xff0c;当下我们所经历的这样一个时代&#xff0c;其实是与互联网并没有太多联…...

【C#Unity题】1.委托和事件在使用上的区别是什么?2.C#中 == 和 Equals 的区别是什么?

1.委托和事件在使用上的区别是什么&#xff1f; 委托和事件是C#中的重要概念&#xff0c;通俗来讲&#xff0c;委托是一个可以指向特定方法的指针&#xff0c;可以将委托分配给不同的脚本&#xff0c;使它们能够完成不同的任务。而事件则是一种使用委托实现的通知机制&#xff…...

FFmpeg5.0源码阅读——内存池AVBufferPool

摘要&#xff1a;FFmpeg中大多数数据存储比如AVFrame,AVPacket都是通过AVBufferRef管理的&#xff0c;而承载数据的结构为AVBuffer。本文主要通过FFmpeg源码来分析下FFmpeg中AVBuffer相关的实现。 关键字&#xff1a;AVBuffer、AVBufferPool、AVBufferPool 1. AVBufferRef 1.…...

Python学习------起步7(字符串的连接、删除、修改、查询与统计、类型判断及字符串字母大小写转换)

目录 前言&#xff1a; 1.字符串的连接 join() 函数 2.字符串的删除&取代 replace()函数 3.字符串的修改&切割 &#xff08;1&#xff09;strip() 函数 &#xff08;2&#xff09;lstrip()函数 和 rstrip()函数 &#xff08;3&#xff09;split()函数-->…...

雪花算法snowflake

snowflake中文的意思是 雪花&#xff0c;雪片&#xff0c;所以翻译成雪花算法。它最早是twitter内部使用的分布式环境下的唯一ID生成算法。在2014年开源。雪花算法产生的背景当然是twitter高并发环境下对唯一ID生成的需求&#xff0c;得益于twitter内部高超的技术&#xff0c;雪…...

Part 4 描述性统计分析(占比 10%)——上

文章目录【后续会持续更新CDA Level I&II备考相关内容&#xff0c;敬请期待】【考试大纲】【考试内容】【备考资料】1、统计基本概念1.1、统计学的含义及应用1.1.1、统计学的含义1.2.1、统计学的应用1.2、统计学的基本概念1.2.1、数据及数据的分类1.2.2、总体和样本1.2.3、…...

Linux系统安全:安全技术和防火墙

目录 一、安全技术 1、安全技术 2、防火墙分类 二、防火墙 1、iptables五表五链 2、黑白名单 3、iptables基本语法 4、iptables选项 5、控制类型 6、隐藏扩展模块 7、显示扩展模块 8、iptables规则保存 9、自定义链使用 一、安全技术 1、安全技术 ①入侵检测系统…...

【干货】Python:turtle库的用法

【干货】Python&#xff1a;turtle库的用法1. turtle库概述2. turtle库与基本绘图2.1 导入库的三种方式2.1.12.1.22.1.32.2 窗体函数2.2 画笔状态函数2.2.1 seed(s)2.2.2 random()2.2.3 randint(a, b)2.2.4 getrandbits(k)2.2.5 randrange(start, stop[ , step])2.2.6 uniform(…...

信息安全与网络安全有什么区别?

生活中我们经常会听到要保障自己的或者企业的信息安全。那到底什么是信息安全呢&#xff1f;信息安全包含哪些内容&#xff1f;与网络安全又有什么区别呢&#xff1f;今天我们就一起来详细了解一下。什么叫做信息安全&#xff1f;信息安全定义如下&#xff1a;为数据处理系统建…...

花了5年时间,用过市面上95%的工具,终于找到这款万能报表工具

经常有粉丝问我有“哪个报表工具好用易上手&#xff1f;”或者是“有哪些适合绝大多数普通职场人的万能报表工具&#xff1f;” 从这里我大概总结出了大家选择报表工具最期望满足的3点&#xff1a; &#xff08;1&#xff09;简单易上手&#xff1a;也就是所谓的学习门槛要低…...

ESP32S3系列--SPI主机驱动详解(一)

一、目的SPI是一种串行同步接口&#xff0c;可用于与外围设备进行通信。ESP32S3自带4个SPI控制器外设&#xff0c;其中SPI0/SPI1内部专用,共用一组信号线,通过一个仲裁器访问外部Flash和PSRAM&#xff1b;SPI2/3各自使用一组信号线&#xff1b;开发者可以使用SPI2/3控制外部SPI…...

2023开工开学火热!远行的人们,把淘特箱包送上顶流

春暖花开&#xff0c;被疫情偷走的三年在今年开学季找补回来了。多个数据反馈&#xff0c;居民消费意愿大幅提升。在淘特上&#xff0c;开工开学节点就很是明显&#xff1a;1月30日以来&#xff0c;淘特箱包品类甚至远超2022年双11&#xff0c;成为开年“第一爆品”。与此同时&…...

怎样免费给自己的公司做网站/苏州网站建设公司

Java进程使用的虚拟内存确实比Java Heap要大很多。JVM包括很多子系统&#xff1a;垃圾收集器、类加载系统、JIT编译器等等&#xff0c;这些子系统各自都需要一定数量的RAM才能正常工作。当一个Java进程运行时&#xff0c;也不仅仅是JVM在消耗RAM&#xff0c;很多本地库&#xf…...

晋江做网站的公司/大数据免费查询平台

一、效果图展示 二、FileHeader 插件安装 FileHeader 插件的安装方法和其它插件相同。下面简单述说一下&#xff1a; 先安装一个 Package Control 插件。相信大家使用 Sublime 的话都有安装这个了Preference -> Package Control -> Install Package -> FileHeader。然…...

长沙哪个平台做网站好/扬中网站制作

使用TM1650四位数码管模块&#xff0c;显示当前光照强度 主程序&#xff1a; from microbit import * from FourDigitDisplay import FourDigitDisplayfdd FourDigitDisplay() fdd.intensity(8)while True:n display.read_light_level()if n > 100:pin0.write_digital(0)…...

临沂住房和城乡建设局网站/网络营销策划方案

本文记载了如何在微信小程序里面实现下拉刷新&#xff0c;上拉加载更多 先开看一下界面 大致如此的界面吧。 这个Demo使用了微信的几个Api和事件&#xff0c;我先列出来。 1.wx.request &#xff08;获取远程服务器的数据&#xff0c;可以理解成$.ajax&#xff09; 2. scroll-v…...

汕头政务发布/网站怎么优化

如今&#xff0c;使用Android等技术以及许多智能手机应用程序&#xff0c;计算机应用程序变得更加复杂&#xff0c;前端越复杂&#xff0c;后端就越复杂。 因此&#xff0c;了解数据库测试、有效地验证数据库&#xff0c;以确保数据库的安全性和质量就显得尤为重要。 在本文中…...

上海做网站的费用/站长之家是什么

C是一种编程语言&#xff0c;但又不是一种单一的编程语言&#xff0c;它可以包含以下四种子语言&#xff0c;也即C的四个组成部分&#xff1a; 1、C部分。C语言的基本语法&#xff0c;内置类型、预处理、数组、指针等。 2、面向对象部分。类&#xff0c;封装、继承、多态、虚…...