07JVM_内存模型和CAS与原子类

2023-09-15 16:05:59

一、内存模型

1.java内存模型

Java内存结构是JMM(Java Memory Model)的意思。JMM定义了一套在多线程读写共享数据(成员变量,数组)时,对数据原子性,见性,有序性的规则和保障。

1.1 原子性

什么是原子性?

原子性是指一个操作是不可中断的,即使多个线程一起执行,一个线程一旦开始,就不会被其他线程干扰。

如何保证原子性

synchronized(同步关键字)

synchronized(对象){

  原子操作代码

}

从第一个线程开始,给这个对象加,可以安全执行原子操作代码。其他线程需要排队等候

synchronized解决并发问题

②各种Lock

synchronized 和各种 Lock 可以保证任一时刻只有一个线程访问该代码块,因此可以保障原子性

1.2 可见性

什么是可见性?

可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。

如何保证可见性

在 Java 中,可以借助synchronized、volatile 以及各种 Lock 实现可见性。如果我们将变量声明为 volatile ,这就指示 JVM,这个变量是共享且不稳定的,每次使用它都到主存中进行读取。

volatile

修饰成员变量和静态成员变量,避免线程从自己的工作缓存查找变量的值,必须到主存获取它的值,线程操作volatile变量都是直接操作主存

1.3有序性

什么是有序性?

①由于指令重排序问题,代码的执行顺序未必就是编写代码时候的顺序。

②指令重排序可以保证串行语义一致,但是没有义务保证多线程间的语义也一致 ,所以在多线程下,指令重排序可能会导致一些问题。

③在Java中,volatile关键字可以禁止指令进行重排序优化

2.happens-before

介绍

happens-before规定哪些写操作对其他线程的读操作可见。是可见性有序性的一套规则。

如何保证

①volatile

②synchronized

二、CAS与原子类

1.CAS无锁并发概述

1.介绍

①CAS全称compare and swap比较并交换

②当多个线程同时操作同一个资源,只能有一个线程操作成功。但是不会阻塞其他线程,其他线程只会收到操作失败的信号。

③CAS是一个乐观锁

补充

乐观锁:认为数据在一般情况下不会产生冲突,所以在数据提交更新的时候,才会对数据是否产生并发冲突进行检测,如果发现并发冲突,则返回错误信息,返回的错误信息可以根据自己的业务进行处理

悲观锁:总是假设最坏的情况,每次在获取共享数据的时候,都认为别人会修改,所以每次都在获取数据的时候加锁。共享资源每次只会给一个线程使用,其他线程阻塞,用完再把资源给其他线程

2.工作流程

读写的内存值V

进行比较的值A

需要写入的新值B

①内存中的原数据V,旧值A,修改的新值B。

比较A与V是否相等

③如果相等,将B写入V(交换)

④返回操作是否成功

3.代码分析

多个线程对一个共享的整型变量执行+1操作

①CAS不加锁,使用while(true)死循环不管尝试/

共享变量是从内存读取的,所以保证变量的可见性。使用volatile修饰

③调用compareAndSwap(旧值,新值)进行比较。

④compareAndSwap操作成功退出循环。

⑤compareAndSwap操作失败,说明其他线程把这个共享变量修改了。需要再次循环读取

注意:

①CAS和volatile结合实现无锁并发,适用竞争不激烈多核CPU(循环重试)

②竞争激烈,重试频繁发生,降低效率

③没有使用用synchronized,线程不会阻塞,提升效率。

4.CAS的缺点

ABA问题,CAS更新操作的时候检查内存值是否变化,没有变化更新内存值。如果原来内存值A,后来变成B,然后再变回A。出现ABA问题,CAS检查没有变化,实际变化了。解决方法就是变量前面加一个版本号,每次更新版本号加1。这样变化成了1A2B3A

②循环时间长,开销大。CAS操作长时间不成功,会导致一直循环。CPU开销大

③只保证一个共享变量的原子操作。对一共享变量执行操作时,CAS能够保证原子操作,但对多个共享变量操作时,CAS无法保证操作的原子性。

2.CAS底层实现

介绍

CAS底层是依赖一个Unsafe直接调用操作系统底层的CAS指令。

调用UnSafe类中的CAS方法,JVM会帮我们实现出CAS汇编指令

部分代码

public final boolean compareAndSet(int expect, int update) {

        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);

}

参数说明

this Unsafe对象

valueOffset 共享变量的地址

expect 旧值

update 新值

如果原子变量中的 value 值等于 expect,则使用 update 值更新该值并返回 true,否则返回 false。

3.原子操作类

juc提供原子操作类,可以提供线程安全的操作。AtomicInteger,AtomicBoolean。底层实现是CAS+volatile实现

更多推荐

在内网部署docker工程总结

前言本次部署的内容主要包括:mysql,redis,nacos,java项目,前端项目,python项目。一安装docker环境首先在拥有网络环境的电脑上下载docker安装包,下载地址可以参考如下:https://download.docker.com/linux/static/stable/x86_64/下载完成之

RapidSSL的便宜单域名https证书

RapidSSL是Geotrusthttps证书品牌中的一款入门级https证书品牌,目前属于Digicert的子品牌。它是一款提供高性价比和广泛适用范围的https证书,无论是个人还是企业用户都可以轻松申请并快速验证。今天就随SSL盾小编了解RapidSSL旗下的单域名https证书。1.RapidSSL旗下的单域名

百望云亮相服贸会 重磅发布业财税融Copilot

小望小望,我要一杯拿铁!好的,已下单成功,请问要开具发票嘛?在获得确认的指令后,百小望AI智能助手按用户要求成功开具了一张电子发票!这是2023年服贸会国家会议中心·成果发布现场,百望云向与会嘉宾展示的业财税融Copilot产品的一个应用场景:在对接百望云后,咖啡师只需专注地制作咖啡,百小望AI智能助手即能完成接单、支

【深入浅出设计模式--命令模式】

深入浅出设计模式--命令模式一、背景二、问题三、解决方案四、试用场景总结五、后记一、背景命令模式是一种行为设计模式,它可以将用户的命令请求转化为一个包含有相关参数信息的对象,命令的发送者不需要知道接收者是如何处理这条命令,多个功能入口可以发送同一命令,避免多处多次实现相同功能的冗余代码。另外可以对命令进行延迟处理,或放

【RocketMQ】消息中间件学习笔记

【RocketMQ】消息中间件学习笔记【一】RocketMQ概述【1】MQ简介【2】MQ永用途(1)限流削峰(2)异步解耦(3)数据收集【3】RocketMQ介绍(1)RocketMQ特点(2)RocketMQ优势【4】RocketMQ基本概念(1)NameServer(2)Broker(3)生产者(Producer)

亚马逊六页纸

一、什么是亚马逊6页纸?亚马逊在内部管理实践中,特别是会议管理上,禁止使用PPT,而是使用一种简洁的「结构化备忘录」,也就是我们熟知的“六页纸”。二、具体解释1、Whatwedo?背景,什么情况下,我们做了什么。因为XXX产品即将量产,我们已启动XXX下一版升级产品的规划。今天开会的主题就是汇报与同步目前的规划情况。2

JS的WebAPI

WebAPI背景知识什么是WebAPI前面学习的JS分成三个大的部分ECMAScript:基础语法部分DOMAPI:操作页面结构BOMAPI:操作浏览器WebAPI就包含了DOM+BOM.什么是APIAPI是一个更广义的概念.而WebAPI是一个更具体的概念,特指DOM+BOM,所谓的API本质上就是一些现成的函数/对

【视觉SLAM入门】9.1 建图1---SLAM任务,稠密地图构建,立体视觉,RGBD,八叉树,点云地图等各种不同地图

"讷为君子,寡为吉人”1.立体稠密地图1.1地图构建1.2分析立体相机稠密建图效果2.RGB-D稠密地图2.1地图对比2.1.1八叉树地图3.建图?定位?孰轻孰重3.1鬼影问题3.2三维重建4.总结SLAM的功能:直到现在我们可以知道SLAM包含:定位,导航,避障,重建,交互。在不同的功能下也有不同的地图。之前的都是稠

计算机毕设 python图像检索系统设计与实现

文章目录0前言1课题简介2图像检索介绍(1)无监督图像检索(2)有监督图像检索3图像检索步骤4应用实例5最后0前言🔥这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。为了大家能够顺利以及最少的精力通过

Rockchip RK3399 - USB触摸屏接口驱动

----------------------------------------------------------------------------------------------------------------------------开发板:NanoPC-T4开发板eMMC:16GBLPDDR3:4GB显

spring:实现初始化动态bean|获取对象型数组配置文件

0.引言近期因为要完成实现中间件的工具包组件,其中涉及要读取对象型的数组配置文件,并且还要将其加载为bean,因为使用了spring4.3.25.RELEASE版本,很多springboot的相关特性无法支持,因此特此记录,以方便后续同学有相同情况可以参考1.获取对象型数组配置文件首先对象型数组配置文件如下所示:min

热文推荐