JUC并发编程学习笔记(十九)原子引用
原子引用
带版本号的原子操作!
解决ABA问题,引入原子引用(乐观锁思想)
AtomicStampedReference类解决ABA问题
package org.example.cas;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;
//使用原子引用解决ABA问题
public class ABADemo {
public static void main(String[] args) {
//默认值 默认版本号(时间戳)
//如果泛型是一个包装类,注意对象引用的问题
//正常在业务中里面比较并交换的一般是一个个对象如User这种
AtomicStampedReference<Integer> atomic = new AtomicStampedReference<>(1,1);
new Thread(()->{
int stamp = atomic.getStamp();//获得版本号
System.out.println("a1版本号=》"+stamp);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//atomic.compareAndSet 期待的值 更新的值 期待的版本号 更新的版本号
//当期待的值和期待的版本号都满足期待时,就更新值和版本号
System.out.println(atomic.compareAndSet(1, 2, stamp, stamp + 1));
System.out.println("a2版本号=》"+atomic.getStamp());
System.out.println(atomic.compareAndSet(2, 1, atomic.getStamp(), atomic.getStamp() + 1));
System.out.println("a3版本号=》"+atomic.getStamp());
},"A").start();
//与乐观锁原理相同
new Thread(()->{
int stamp = atomic.getStamp();//获得版本号
System.out.println("b1版本号=》"+stamp);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(atomic.compareAndSet(1, 2, stamp, stamp + 1));
System.out.println("b2版本号=》"+atomic.getStamp());
},"B").start();
}
}
所有相同类型的包装类对象之间值的比较全部使用equals方法比较
Integer使用了对象缓存机制,默认范围是-128至127,推荐使用静态工厂方法valueOf获取对象实例,而不是new,因为valueOf使用缓存,而new一定会创建新的对象分配新的内存空间;
说明:对于Integer var = ?在-128至127之间的赋值,Integer对象实在IntegerCache.cache产生,会复用已有对象,这个区间的Integer值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用equals方法进行判断。
JUC并发编程学习笔记(十九)原子引用的更多相关文章
- JUC并发编程学习笔记
JUC并发编程学习笔记 狂神JUC并发编程 总的来说还可以,学到一些新知识,但很多是学过的了,深入的部分不多. 线程与进程 进程:一个程序,程序的集合,比如一个音乐播发器,QQ程序等.一个进程往往包含 ...
- Java并发编程学习笔记
Java编程思想,并发编程学习笔记. 一.基本的线程机制 1.定义任务:Runnable接口 线程可以驱动任务,因此需要一种描述任务的方式,这可以由Runnable接口来提供.要想定义任务,只需实现R ...
- 并发编程学习笔记(9)----AQS的共享模式源码分析及CountDownLatch使用及原理
1. AQS共享模式 前面已经说过了AQS的原理及独享模式的源码分析,今天就来学习共享模式下的AQS的几个接口的源码. 首先还是从顶级接口acquireShared()方法入手: public fin ...
- 并发编程学习笔记(6)----公平锁和ReentrantReadWriteLock使用及原理
(一)公平锁 1.什么是公平锁? 公平锁指的是在某个线程释放锁之后,等待的线程获取锁的策略是以请求获取锁的时间为标准的,即使先请求获取锁的线程先拿到锁. 2.在java中的实现? 在java的并发包中 ...
- python3.4学习笔记(十九) 同一台机器同时安装 python2.7 和 python3.4的解决方法
python3.4学习笔记(十九) 同一台机器同时安装 python2.7 和 python3.4的解决方法 同一台机器同时安装 python2.7 和 python3.4不会冲突.安装在不同目录,然 ...
- 并发编程学习笔记(15)----Executor框架的使用
Executor执行已提交的 Runnable 任务的对象.此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节.调度等)分离开来的方法.通常使用 Executor 而不是显式地创建 ...
- 并发编程学习笔记(14)----ThreadPoolExecutor(线程池)的使用及原理
1. 概述 1.1 什么是线程池 与jdbc连接池类似,在创建线程池或销毁线程时,会消耗大量的系统资源,因此在java中提出了线程池的概念,预先创建好固定数量的线程,当有任务需要线程去执行时,不用再去 ...
- 并发编程学习笔记(13)----ConcurrentLinkedQueue(非阻塞队列)和BlockingQueue(阻塞队列)原理
· 在并发编程中,我们有时候会需要使用到线程安全的队列,而在Java中如果我们需要实现队列可以有两种方式,一种是阻塞式队列.另一种是非阻塞式的队列,阻塞式队列采用锁来实现,而非阻塞式队列则是采用cas ...
- 并发编程学习笔记(11)----FutureTask的使用及实现
1. Future的使用 Future模式解决的问题是.在实际的运用场景中,可能某一个任务执行起来非常耗时,如果我们线程一直等着该任务执行完成再去执行其他的代码,就会损耗很大的性能,而Future接口 ...
- 并发编程学习笔记(12)----Fork/Join框架
1. Fork/Join 的概念 Fork指的是将系统进程分成多个执行分支(线程),Join即是等待,当fork()方法创建了多个线程之后,需要等待这些分支执行完毕之后,才能得到最终的结果,因此joi ...
随机推荐
- GFLV2:边界框不确定性的进一步融合,提点神器 | CVPR 2021
GFLV2基于GFLV1的bbox分布进行改进,将分布的统计信息融入到定位质量估计中,整体思想十分创新和完备,从实验结果来看,效果还是挺不错的 来源:晓飞的算法工程笔记 公众号 论文: Gener ...
- 05 CMMI(Capability Maturity Model Integration)【软件过程与管理】
CMMI(Capability Maturity Model Integration) CMMI成熟度等级 执行的:过程不可预测,缺乏控制,反应式的 已管理的:项目描绘过程,而且经常是反应式的 已定义 ...
- 详解数仓对象设计中序列SEQUENCE原理与应用
本文分享自华为云社区<GaussDB(DWS)对象设计之序列SEQUENCE原理与使用方法介绍>,作者:VV一笑. 1. 前言 适用版本:8.2.1及以上版本 序列SEQUENCE用来生成 ...
- .NET Emit 入门教程:第六部分:IL 指令:3:详解 ILGenerator 指令方法:参数加载指令
前言: 在上一篇中,我们介绍了 ILGenerator 辅助方法. 本篇,将详细介绍指令方法,并详细介绍指令的相关用法. 在接下来的教程,关于IL指令部分,会将指令分为以下几个分类进行讲解: 1.参数 ...
- OpenHarmony创新赛 | 您有一份创新激励奖待领取 请查收!
2023开源和信息消费大赛 开放原子开源大赛OpenHarmony创新赛 (以下简称"OpenHarmony创新赛") 正如火如荼的进行当中 赛程也即将进入到提交作品的关键阶段 ...
- Demo Day直播 | 成长计划解决方案学生挑战赛一等奖即将揭晓!
OpenAtom OpenHarmony开源开发者成长计划 解决方案学生挑战赛 Demo Day来袭! 每一支队伍 心怀梦想,攻坚克难 迸发出照亮世界的火花 用技术推动世界进步 与你一起,共创未来 ...
- C++ Break、Continue 和 数组操作详解
C++ Break 和 Continue break 语句还可以用来跳出循环. 在以下示例中,当 i 等于 4 时跳出循环: for (int i = 0; i < 10; i++) { if ...
- 深入了解 Python MongoDB 查询:find 和 find_one 方法完全解析
在 MongoDB 中,我们使用 find() 和 find_one() 方法来在集合中查找数据,就像在MySQL数据库中使用 SELECT 语句来在表中查找数据一样 查找单个文档 要从MongoDB ...
- Numpy数组变形和轴变换
数组变形(reshape)或轴转换(Transposing Arrays and Swapping Axes)后返回的是非副本视图,对于非副本视图的修改会使原来的数组也同时改变. In [1]: im ...
- 生成 MFC ActiveX (OCX)时,报错:MSB801:未能注册输出
我们在生成 ocx 控件时,报错:MSB801:未能注册输出,如下图: 解决方法: 1.打开 项目属性 -> 链接器 -> 常规 : 逐用户重定向 改为 是 2. 重新生成 如果此时 ...