并发编程之Atomic原子操作类
基本类型:AtomicInteger、AtomicBoolean、AtomicLong
引用类型:AtomicReference、AtomicMarkableReference、AtomicStampedReference
数组类型:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray
对象属性原子修改器:AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater
原子类型累加器:DoubleAccumulator、DoubleAdder、LongAccumulator、LongAdder、Striped64
1. 基本类型
以AtomicInteger为例,它提供了原子计数器和比较交换功能
1.1 原子计数器
addAndGet()- 以原子方式将给定值添加到当前值,并在添加后返回新值。
getAndAdd() - 以原子方式将给定值添加到当前值并返回旧值。
incrementAndGet()- 以原子方式将当前值递增1并在递增后返回新值。它相当于i ++操作。
getAndIncrement() - 以原子方式递增当前值并返回旧值。它相当于++ i操作。
decrementAndGet()- 原子地将当前值减1并在减量后返回新值。它等同于i-操作。
getAndDecrement() - 以原子方式递减当前值并返回旧值。它相当于-i操作。
使用示例:
package org.example.concurrent;import lombok.extern.slf4j.Slf4j;
import org.junit.Test;import java.util.concurrent.atomic.AtomicInteger;@Slf4j
public class AtomicIntegerTest {@Testpublic void test() {AtomicInteger atomic = new AtomicInteger(0);log.debug("atomic={}", atomic);log.debug("atomic.addAndGet(1)={}, atomic={}", atomic.addAndGet(1), atomic);log.debug("atomic.getAndAdd(1)={}, atomic={}", atomic.getAndAdd(1), atomic);log.debug("atomic.incrementAndGet()={}, atomic={}", atomic.incrementAndGet(), atomic);log.debug("atomic.getAndIncrement()={}, atomic={}", atomic.getAndIncrement(), atomic);log.debug("atomic.decrementAndGet()={}, atomic={}", atomic.decrementAndGet(), atomic);log.debug("atomic.getAndDecrement()={}, atomic={}", atomic.getAndDecrement(), atomic);}
}
打印结果:
18:34:38.578 [main] DEBUG o.e.concurrent.AtomicIntegerTest - atomic=0
18:34:38.581 [main] DEBUG o.e.concurrent.AtomicIntegerTest - atomic.addAndGet(1)=1, atomic=1
18:34:38.581 [main] DEBUG o.e.concurrent.AtomicIntegerTest - atomic.getAndAdd(1)=1, atomic=2
18:34:38.581 [main] DEBUG o.e.concurrent.AtomicIntegerTest - atomic.incrementAndGet()=3, atomic=3
18:34:38.581 [main] DEBUG o.e.concurrent.AtomicIntegerTest - atomic.getAndIncrement()=3, atomic=4
18:34:38.581 [main] DEBUG o.e.concurrent.AtomicIntegerTest - atomic.decrementAndGet()=3, atomic=3
18:34:38.581 [main] DEBUG o.e.concurrent.AtomicIntegerTest - atomic.getAndDecrement()=3, atomic=2
1.2 比较和交换功能
比较和交换操作将内存中的内容与给定值进行比较,并且只有它们相同时,才将该内存位置的内容修改为给定的新值。这是作为单个原子操作完成的。
boolean compareAndSet(int expect, int update);//设置成功返回true,否则返回false
代码示例:
package org.example.concurrent;import lombok.extern.slf4j.Slf4j;
import org.junit.Test;import java.util.concurrent.atomic.AtomicInteger;@Slf4j
public class AtomicIntegerTest {@Testpublic void test() {AtomicInteger atomic = new AtomicInteger(0);log.debug("atomic={}, atomic.compareAndSet(0, 22) = {}", atomic.get(),atomic.compareAndSet(0, 22));// atomic中的值已经为22, 下面的修改会失败log.debug("atomic={}, atomic.compareAndSet(0, 22) = {}", atomic.get(),atomic.compareAndSet(0, 22));}
}
打印结果:
19:03:32.844 [main] DEBUG o.e.concurrent.AtomicIntegerTest - atomic=0, atomic.compareAndSet(0, 22) = true
19:03:32.847 [main] DEBUG o.e.concurrent.AtomicIntegerTest - atomic=22, atomic.compareAndSet(0, 22) = false
2. 引用类型
2.1 AtomicReference
原子引用可以保证你在修改引用的对象时(引用对象1改为引用对象2)的线程安全性。compareAndSet比较的是否是相同的对象,不是调用对象的equal比较。
示例:
package org.example.concurrent;import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;import java.util.concurrent.atomic.AtomicReference;@Slf4j
public class AtomicReferenceTest {@Testpublic void test() {Person person1 = new Person("张三");Person person2 = new Person("李四");AtomicReference<Person> atomic = new AtomicReference<>(person1);log.debug("atomic={}, atomic.compareAndSet({}, {}) = {}", atomic.get(), person1, person2,atomic.compareAndSet(person1, person2));log.debug("atomic={}, atomic.compareAndSet({}, {}) = {}", atomic.get(), person1, person2,atomic.compareAndSet(person1, person2));// 创建一个新的李四对象,设置仍然失败log.debug("atomic={}, atomic.compareAndSet({}, {}) = {}", atomic.get(), person2, person1,atomic.compareAndSet(new Person("李四"), person1));}@AllArgsConstructor@Getter@EqualsAndHashCodepublic static class Person {private final String name;@Overridepublic String toString() {return getName();}}
}
打印结果:
19:01:21.260 [main] DEBUG o.e.concurrent.AtomicReferenceTest - atomic=张三, atomic.compareAndSet(张三, 李四) = true
19:01:21.263 [main] DEBUG o.e.concurrent.AtomicReferenceTest - atomic=李四, atomic.compareAndSet(张三, 李四) = false
19:01:21.263 [main] DEBUG o.e.concurrent.AtomicReferenceTest - atomic=李四, atomic.compareAndSet(李四, 张三) = false
2.2 AtomicMarkableReference 带标记的原子引用
标记只能携带true和false两个值。提供的方法有:
- getReference() 获取当前引用的对象
- isMarked() 返回标记的值
-
compareAndSet(refer, newRefer, mark, newMark),引用对象和标记都相同时,重新设置引用和标记,返回更新成功/失败
-
boolean attemptMark(ref, newMark), 引用对象相同时,更新标记,返回跟新成功/失败
代码示例:
package org.example.concurrent;import lombok.extern.slf4j.Slf4j;
import org.junit.Test;import java.util.concurrent.atomic.AtomicMarkableReference;@Slf4j
public class AtomicMarkableReferenceTest {@Testpublic void test() {AtomicMarkableReference<String> atomic = new AtomicMarkableReference<>("abc", true);log.debug("reference = {}, mark={}", atomic.getReference(), atomic.isMarked());log.debug("atomic.compareAndSet(\"abc\",\"def\", false, true) = {}",atomic.compareAndSet("abc", "def", false, true));log.debug("atomic.compareAndSet(\"abc\",\"def\", false, true) = {}",atomic.compareAndSet("abc", "def", true, true));log.debug("reference = {}, mark={}", atomic.getReference(), atomic.isMarked());log.debug("atomic.attemptMark(\"def\", false) = {}, atomicMark={}",atomic.attemptMark("def", false), atomic.isMarked());}
}
执行结果:
19:48:27.319 [main] DEBUG o.e.c.AtomicMarkableReferenceTest - reference = abc, mark=true
19:48:27.322 [main] DEBUG o.e.c.AtomicMarkableReferenceTest - atomic.compareAndSet("abc","def", false, true) = false
19:48:27.322 [main] DEBUG o.e.c.AtomicMarkableReferenceTest - atomic.compareAndSet("abc","def", false, true) = true
19:48:27.322 [main] DEBUG o.e.c.AtomicMarkableReferenceTest - reference = def, mark=true
19:48:27.322 [main] DEBUG o.e.c.AtomicMarkableReferenceTest - atomic.attemptMark("def", false) = true, atomicMark=false
2.3 AtomicStampedReference带版本号的原子引用
AtomicStampedReference 和 AtomicMarkableReference类似,只不过标记由boolean改为了int,方法attemptMark变为了attemptStamp;方法isMarked变为了getStamp
3. 数组类型
AtomicIntegerArray对数组元素的操作是原子的,提供基于数组下标的get,set,compareAndSet等操作。创建时需要提供操作的数组或者指定数组的大小。
package org.example.concurrent;import lombok.extern.slf4j.Slf4j;
import org.junit.Test;import java.util.concurrent.atomic.AtomicIntegerArray;@Slf4j
public class AtomicIntegerArrayTest {@Testpublic void test() {// 创建有10个元素的数组AtomicIntegerArray atomic = new AtomicIntegerArray(10);atomic.set(0, 1); // 第0个位置设置为1atomic.get(0); // 获取第0个位置的值。atomic.getAndAdd(2, 1); // 获取第2个位置的值,数组中的值+1atomic.compareAndSet(0, 1, 2); // 第0个位置的值如果时1的话,修改为2}
}
相关文章:
并发编程之Atomic原子操作类
基本类型:AtomicInteger、AtomicBoolean、AtomicLong 引用类型:AtomicReference、AtomicMarkableReference、AtomicStampedReference 数组类型:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray 对象属性原子修改器:…...

管家婆辉煌Ⅱ 13.32版安装方法
因管家婆辉煌版已经长期不更新,现已经出现蓝屏的问题,故此新开此贴,慢慢更新安装方法。 首先管家婆下载地址:http://www.grasp.com.cn/download.aspx?id116 先安装sql server 2008 下载后,运行安装,请注…...

常见的接口优化技巧思路
一、背景 针对老项目,去年做了许多降本增效的事情,其中发现最多的就是接口耗时过长的问题,就集中搞了一次接口性能优化。本文将给小伙伴们分享一下接口优化的通用方案。 二、接口优化方案总结 1.批处理 批量思想:批量操作数据…...

【Java EE】-使用Fiddler抓包以及HTTP的报文格式
作者:学Java的冬瓜 博客主页:☀冬瓜的主页🌙 专栏:【JavaEE】 分享: 在满园弥漫的沉静的光芒之前,一个人更容易看到时间,并看到自己的身影。——史铁生《我与地坛》 主要内容:使用FIddler抓包的…...
Java异步编程
Java异步编程 1、什么是java异步编程2、异步编程有什么作用3、异步编程常用于哪些业务4、异步编程的方式5、Async异步调用Async简介 1、什么是java异步编程 Java异步编程是一种处理并发问题的技术,它可以在执行耗时操作的同时,不阻塞主线程,…...

C++类与对象(二)——构造函数与析构函数
文章目录 一.类的默认6个成员函数二.构造函数1.引例2.构造函数的概念及特性 三.析构函数😋析构函数的特性 前言: 上篇文章初步认识了类以及类的相关知识,本篇将继续深入学习类与对象——类的默认6个成员函数: 一.类的默认6个成员函…...

c++标准模板(STL)(std::array)(四)
定义于头文件 <array> template< class T, std::size_t N > struct array;(C11 起) std::array 是封装固定大小数组的容器。 此容器是一个聚合类型,其语义等同于保有一个 C 风格数组 T[N] 作为其唯一非静态数据成员的结构体。不同于 C 风格数…...

vue3计算属性
计算属性 模板中的表达式虽然方便,但也只能用来做简单的操作。如果在模板中写太多逻辑,会让模板变得臃肿,难以维护。推荐使用计算属性来描述依赖响应式状态的复杂逻辑 基础示例 不够好的示例 模板中使用了表达式,不够直观&…...
Java 中的访问修饰符有哪些(九)
Java 中的访问修饰符用于限制类、接口、字段和方法的访问范围,它们分别表示不同的访问控制级别。Java 中共有四种访问修饰符:public、protected、default 和 private。 public public 是最开放的访问修饰符,用于指定公共访问级别。被 publi…...

HR员工管理的三重境界:管事、管人、管心
在一个公司里,员工来来往往是常态,虽说我们不能替他们决定,但是一定是与公司的管理者有一定的关系。马云曾经说过:“一个员工离职,不外乎两种原因,一是钱没给到位;二是心里委屈了”。一句话就是…...

延迟队列与SpringBoot实战
延迟队列与SpringBoot实战 概念 延时队列,队列内部是有序的,最重要的特性就体现在它的延时属性上,延时队列中的元素是希望在指定时间到了以后或之前取出和处理,简单来说,延时队列就是用来存放需要在指定时间被处理的元素的队列 …...
【算法】九键输入法
题目: 输入数字字符串, 输出这串字符对应的九键输入法有可能出现的所有情况 算法: 定义了一个全局变量 g_numStr,其中存储了每个数字对应的字母。定义了一个递归函数 str_combine,用于将每个数字对应的字母进行组合。str_combin…...

jvm之类加载器
写在前面 当我们通过javac命令将java源代码编译为Java字节码后,必须通过类加载器将其加载到jvm中才能运行,所以类加载器是jvm中非常重要的一个组成部分,本文我们就一起来看下吧! 1:类的生命周期 类的生命周期如下图…...

Chapter4:频率响应法(上)
第四章:频率响应法 Exercise4.1 已知微分网络和积分网络电路图如下图所示,求网络的频率特性。 解: 【图 ( a ) ({\rm a}) (a)微分网络】 由微分网络电路图可得:...

【6. 激光雷达接入ROS】
欢迎大家阅读2345VOR的博客【6. 激光雷达接入ROS】🥳🥳🥳 2345VOR鹏鹏主页: 已获得CSDN《嵌入式领域优质创作者》称号👻👻👻,座右铭:脚踏实地,仰望星空&#…...

Java 基础进阶篇(三)—— 面向对象的三大特征之二:继承
文章目录 一、继承概述二、内存运行原理 ★三、继承的特点四、继承后:成员变量和方法的访问特点五、继承后:方法重写六、继承后:子类构造器的特点七、继承后:子类构造器访问父类有参构造器八、this、super 总结 一、继承概述 Jav…...
[angstromctf 2023] 部分
这个比赛打了个开头就放弃了,最近放弃的比较多,国外的网太慢,国内的题太难。 Crypto ranch 这题直接给出密文这提示 rtkw{cf0bj_czbv_nvcc_y4mv_kf_kip_re0kyvi_uivjj1ex_5vw89s3r44901831} Caesar dressing is so 44 BC... 然后是加密程序…...

死信队列
死信队列 死信的概念 先从概念解释上搞清楚这个定义,死信,顾名思义就是无法被消费的消息,字面意思可以这样理解,一般来说,producer 将消息投递到 broker 或者直接到queue 里了,consumer 从 queue 取出消息…...

基于YOLOv5的目标检测系统详解(附MATLAB GUI版代码)
摘要:本文重点介绍了基于YOLOv5目标检测系统的MATLAB实现,用于智能检测物体种类并记录和保存结果,对各种物体检测结果可视化,提高目标识别的便捷性和准确性。本文详细阐述了目标检测系统的原理,并给出MATLAB的实现代码…...

使用ChatGPT工具阅读文献的实战教程
大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...