原子操作的原理和实现

news/2024/5/6 12:34:47/文章来源:https://blog.csdn.net/qq_52240237/article/details/132584093

目录

相关术语

处理器如何实现原子操作

Java如何实现原子操作

循环CAS实现原子操作

使用锁机制实现原子操作


原子操作是指一个或者多个不可再分割的操作。这些操作的执行顺序不能被打乱。

相关术语

缓存行:缓存的最小操作单位

(面试题、重点)比较并且交换(CAS):CAS操作(CAS无锁状态下安全更新数据)需要输入两个数值,一个旧值(期望操作前的值)和一个新值,在操作期间先比较旧值有没有发生变化,如果没有发生变化,才交换成新值,发生了变化则不交换。我们一个线程往回更新的时候会锁总线,其他线程即使切换到也不能传回数据,所有可以在多线程下保证数据的正确性(这个表明我们不能自己写一个cas,需要调用Java核心的Java方法来使用操作系统的cas)

cas有个问题,对中间的感知不清楚(ABA问题)

CPU流水线:每个人只做一件事,没有切换时间,提高总体效率(假如共10个任务,每个任务5个基本指令,共50个基本指令。流水线就会先将所有任务中的相同的基本指令一起执行完之后,再更换线路来执行其他相同的指令,这样减少了线路的切换,而线路切换需要的时间很长)(流水线可能导致顺序错乱问题,在同一个线程中,代码的底层执行顺序可能是乱的,可能执行顺序是先第二行再第一行)

内存顺序冲突:内存顺序冲突一般是由假共享引起的,假共享是指多个CPU同时修改同一个缓存行的不同部分而引起其中一个CPU的操作无效,当出现这个内存顺序冲突时,CPU必须清空流水线

处理器如何实现原子操作

处理器通过总线锁和缓存锁的方式来实现原子操作

总线锁:使用处理器提供的一个LOCK#信号,当一个处理器在总线上输出此信号时,其他处理器的请求将被阻塞住

缓存锁:对应一个内存的不同线程的高速缓存,在操作一个时,其他缓存行全部锁住

跨总线、跨缓存行、跨页:

cpu和内存之间的总线宽度大约36~41位(36~41根导线),单个导线同一时刻传一个电信号;一个缓存行64比特,一个内存页4kb,跨总线、跨缓存行、跨页指的是数据的大小超过单个大小(跨导线可能是long类型的多于41位;缓存行可能是一个批次要处理的数据,不是一个变量;页可能是一个超过4kb大小的综合数据)

锁住总线所有的线程都不能返回,锁缓存与缓存相关的不能返回,但缓存锁有些处理器不支持

Java如何实现原子操作

在Java中可以通过锁和循环CAS的方式来实现原子操作。

循环CAS实现原子操作

JVM中的CAS操作正是利用了处理器提供的CMPXCHG指令实现的。自旋CAS实现的基本思路就是循环进行CAS操作直到成功为止。Java本身实现不了CAS操作,必须依托于操作系统内核

CAS概述

CAS的全称是 Compare-and-Swap,也就是比较并交换,是并发编程中一种常用的算法。它包含了三个参数:V,A,B。其中,V表示要读写的内存位置,A表示旧的预期值,B表示新值。CAS指令执行时,当且仅当V的值等于预期值A时,才会将V的值设为B,如果V和A不同,说明可能是其他线程做了更新,那么当前线程就什么都不做,最后,CAS返回的是V的真实值。而在多线程的情况下,当多个线程同时使用CAS操作一个变量时,只有一个会成功并更新值,其余线程均会失败,但失败的线程不会被挂起,而是不断的再次循环重试。

从Java 1.5开始,JDK的并发包里提供了一些类来支持原子操作,如

AtomicBoolean(用原子方式更新的boolean值)AtomicInteger(用原子方式更新的int值)AtomicLong(用原子方式更新的long值)

线程安全,在多线程操作时,不需要我们手动加锁和各种同步控制,自己内部已经加了。

这些原子包装类还提供了有用的工具方法,比如以原子的方式将当前值自增1和自减1。

调用方法实现cas

(Java中的cas不仅存在于AtomicInteger一个类中,其他类也可以有)

CAS实现原子操作的三大问题

1.(面试题)ABA问题

如果一个值原来是A,变成了B,又变成了A,那么使用CAS进行检查时会发现它的值没有发生变化,但是实际上却变化了。cas没有发现的话还会有线程根据最开始的A认为和旧值相同而接着返回

解决方法:加版本号,每次变量更新的时候把版本号加1,那么A→B→A就会变成1A→2B→3A。

从Java 1.5开始,JDK的Atomic包里提供了一个类AtomicStampedReference,这个类的compareAndSet方法的作用是首先检查当前引用是否等于预期引用,并且检查当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用和该标志的值设置为给定的更新值。

2.循环时间长开销大,自旋CAS如果长时间不成功,会给CPU带来非常大的执行开销

3.只能保证一个共享变量的原子操作

当对一个共享变量执行操作时,我们可以使用循环CAS的方式来保证原子操作,但是对多个共享变量操作时,循环CAS就无法保证操作的原子性,这个时候就可以用锁。也可以将多个共享变量变为一个变量(例:ij = 2a)

cas不加锁可以在多线程下保证了计算的正确率,但是在 高并发情况下,会有很多线程在不符合时重新计算(假如有10000个线程进行计算,一个返回后其余9999都需要重新获取数据计算),很大的损耗了cpu的性能。低并发可以,高并发性能不好

锁里面释放锁获取锁都是cas,是因为重量级锁获取锁的时候用cas获取,一旦失败的话停止cas,进入阻塞队列。不是无限的cas

使用锁机制实现原子操作

锁机制保证了只有获得锁的线程才能够操作锁定的内存区域。JVM内部实现了很多种锁机制,有偏向锁、轻量级锁和互斥锁。有意思的是除了偏向锁,JVM同步块的时候使用循环CAS的方式来获取锁,当它退出同步块的时候使用循环CAS释放锁。实现锁的方式都用了循环CAS,即当一个线程想进入

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

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

相关文章

SQL查询本年每月的数据

--一、以一行数据的形式,显示本年的12月的数据,本示例以2017年为例,根据统计日期字段判断,计算总和,查询语句如下:selectsum(case when datepart(month,统计日期)1 then 支付金额 else 0 end) as 1月, sum…

植物大战僵尸各种僵尸攻略(一)

前言 此文章为“植物大战僵尸”专栏中的004刊(2023年9月第2刊),欢迎订阅。版权所有。 注意: 1.本博客适用于pvz无名版; 2.pvz指植物大战僵尸(Plants VS Zonbies); 3.本文以耗费低做标准&am…

企业应用系统 PHP项目支持管理系统Dreamweaver开发mysql数据库web结构php编程计算机网页

一、源码特点 PHP 项目支持管理系统是一套完善的web设计系统 应用于企业项目管理,从企业内部的各个业务环境总体掌握,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 php项目支撑管理系统2 二、功能介绍 (1)权限管理&#xff1…

PaddleNLP使用Vicuna

LLaMA 模型 LLaMa 是一个大型语言模型,由 Meta 开源。它的全称是 Large Language Model Meta AI,参数量从 70 亿到 650 亿不等。例如,130 亿参数的 LLaMA 模型在大多数基准上可以胜过参数量达 1750 亿的 GPT-3,而且可以在单块 V1…

Python中的绝对和相对导入

在本文中,我们将看到Python中的绝对和相对导入。 Python中导入的工作 Python中的import类似于C/C中的#include header_file。Python模块可以通过使用import导入文件/函数来访问其他模块的代码。import语句是调用import机制的最常见方式,但它不是唯一的…

2023/9/3周报

目录 摘要 文献阅读1 1、标题和提出问题 2、物理模型对于水质预测的缺陷 3、模型框架 4、相关公式 5、结果分析 文献阅读2 1、标题和提出问题 2、问题叙述 3、模型框架 4、误差修补 5、实验结果和分析 总结 摘要 本周阅读了2篇论文,分别为一种基于深…

C++ Primer 第3章 字符串、向量和数组

C Primer 第3章 字符串、向量和数组 3.1 命名空间的using声明一、每个名字都需要独立的using声明二、头文件不应包含using声明三、一点注意事项 3.2 标准库类型string3.2.1 定义和初始化string对象一、直接初始化和拷贝初始化 3.2.2 string对象上的操作一、读写string对象二、读…

CVPR2022 Semi-Supervised Semantic Segmentation Using Unreliable Pseudo-Labels

Semi-Supervised Semantic Segmentation Using Unreliable Pseudo-Labels 使用不可靠的伪标签的半监督语义分割 Paper:https://openaccess.thecvf.com/content/CVPR2022/html/Wang_Semi-Supervised_Semantic_Segmentation_Using_Unreliable_Pseudo-Labels_CVPR_202…

Python 没有 pip 包问题解决

最近需要搞一个干净的Python,从官网上直接下载解压可用的绿色版,发现无法正常使用PiP 一 官网下载Python https://www.python.org/downloads/ 选择 embeddable package,这种是免安装的包,解压后可以直接使用。 二 配置环境变量 添加环境变量&#xff1a…

CXL.mem M2S Message 释义

🔥点击查看精选 CXL 系列文章🔥 🔥点击进入【芯片设计验证】社区,查看更多精彩内容🔥 📢 声明: 🥭 作者主页:【MangoPapa的CSDN主页】。⚠️ 本文首发于CSDN&#xff0c…

基础算法--快速排序

快速排序 算法原理 1. 取一个元素p(第一个元素,最后一个元素,中间元素,随机 都可以),使元素p归位。 2. 列表被p分成两部分,左边都比p小,右边都比p大。 3. 递归完成排序。 动态演示 python代码实现 import…

思维的深度,决定职场的高度

经常有读者问我,自己做事很努力,可是结果却总是不尽如人意,问题究竟出在哪里? 虽然成事的关键因素有很多,但是归根结底其实只有两点,就是做局和破局。也就是,如何识破别人给你做的局&#xff1f…

Feign负载均衡写法

Feign主要为了面向接口编程 feign是web service客户端,是接口实现的,而ribbon是通过微服务名字访问通过RestTemplate调用的,如下: 在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置它(类似…

vue声明周期

1.在created中发送数据 async created(){ const resawait axios.get("url) this.listres.data.data } 2.在mounted中获取焦点 mounted(){ document.querySelector(#inp).focus()

JavaScript基础05——字面量、变量介绍及变量基本使用

哈喽,大家好,我是雷工! 说起变量感觉很熟悉,但要让解释什么是变量时,却有点语塞,就像解释下为啥112一样,感觉非常熟悉,就是知道,但确解释不出来。 不过虽然在其他场景比较…

【无标题】嵌入式开发-IIC通信介绍

IIC(Inter-Integrated Circuit)是一种两线式串行总线协议,用于连接微控制器及其他外围设备。在IIC总线上的数据传输速率可以是标准模式(100Kbit/s),快速模式(400Kbit/s)和高速模式&a…

用 ChatGPT 写代码太省时间了

几个月前,我们聊过陶哲轩使用 ChatGPT 辅助解决数学问题。当时,他觉得虽然测试结果不太令人满意,但也并没有对 ChatGPT 持完全否定的态度。他觉得,像 ChatGPT 这类大型语言模型在数学中可以用来做一些半成品的语义搜索工作&#x…

【项目经验】:elementui表格中表头的多选框换成文字

一.项目需求 表格可以多选,表头都是汉字。。。。类似于这种 二.实现功能 用到的方法 Table Attributes 参数说明类型可选值默认值header-cell-class-name表头单元格的 className 的回调方法,也可以使用字符串为所有表头单元格设置一个固定的 className。…

3、Spring 之IOC 容器 详解

IoC 是 Inversion of Control 的简写,译为“控制反转”,它不是一门技术,而是一种设计思想,是一个重要的面向对象编程法则,能够指导我们如何设计出松耦合、更优良的程序。 Spring 通过 IoC 容器来管理所有 Java 对象的…

【斗罗Ⅱ】最强武魂揭秘,98级玄老、95级言少哲神兽级武魂曝光

Hello,小伙伴们,我是小郑继续为大家深度解析【绝世唐门】 在斗罗大陆动画绝世唐门中,98级玄老已经登场,他是一个很随意的老人,乍眼一看,似乎是一个邋里邋遢、好吃懒做的人,但是实际上他却是史莱克学院重量级…