首页 > 其他分享 >JUC【1.原子类、2.锁Lock、3.阻塞队列、4.并发集合容器、5.并发工具类、6.线程池】、原子类、CAS

JUC【1.原子类、2.锁Lock、3.阻塞队列、4.并发集合容器、5.并发工具类、6.线程池】、原子类、CAS

时间:2024-02-04 14:31:56浏览次数:34  
标签:JUC Java CAS 原子 并发 int 内存 expected

(JUC简介)

转自 极客时间

1. JUC简介

从JDK1.5起,Java API 中提供了java.util.concurrent(简称JUC)包,在此包中定义了并发编程中很常用 的工具,比如:线程池、阻塞队列、同步器、原子类等等。JUC是 JSR 166 标准规范的一个实现,JSR 166 以及 JUC 包的作者是同一个人 Doug Lea 。

在这里插入图片描述

2. 原子类与CAS

通过上面学习volatile,我们发现volatile修饰的变量存在原子性的BUG,这个问题怎么解决呢?难道只能使用Synchronized吗?

2.1 Atomic包

java.util.concurrent.atomic包 从JDK 1.5开始提供了java.util.concurrent.atomic包(以下简称Atomic包),这个包中的原子操作类提 供了一种用法简单、性能高效、线程安全地更新一个变量的方式。可以解决volatile原子性操作变量的问 题。

因为变量的类型有很多种,所以在Atomic包里一共提供了13个类,属于4种类型的原子更新方式,分别 是原子更新基本类型、原子更新数组、原子更新引用和原子更新属性(字段)。Atomic包里的类基本都 是使用Unsafe实现的包装类。

在这里插入图片描述

AtomicInteger主要API如下:

get() //直接返回值
getAndAdd(int) //增加指定的数据,返回变化前的数据
getAndDecrement() //减少1,返回减少前的数据
getAndIncrement() //增加1,返回增加前的数据
getAndset(int) ////增加1,返回增加前的数据

addAndGet(int) //设置指定的数据,返回设置前的数据
decrementAndGet() //减少1,返回减少后的值
incrementAndGet() //增加1,返回增加后的值
1azyset(int) //仅仅当get时才会set
compareAndset(int,int) //尝试新增后对比,若增加成功则返回true否则返回false

用AtomicInteger解决可见性案例中的问题 在这里插入图片描述

2.2 CAS介绍

在这里插入图片描述

2.3 CAS原理详解

Java中对CAS的实现

Java不能像C/C++那样直接操作内存区域,需要通过本地方法(native 方法)来访问。JAVA中的==CAS操作都 是通过sun包下Unsafe类实现==,而==Unsafe类中的方法都是native方法==。

Unsafe类,全限定名是sun.misc.Unsafe,位于在 sun.misc 包下,不属于Java 标准API。 Unsafe对CAS操作的实现有三个

/**
 * Atomically update Java variable to x if it is currently holding expected.
 * @return true if successful
 */
public final native boolean compareAndSwapInt(Object o, long offset, int expected, int x);
/**
 * Atomically update Java variable to x if it is currently holding expected.
 * @return true if successful
 */
public final native boolean compareAndSwapObject(Object o, long offset,Object expected,Object x);
/**
 * Atomically update Java variable to x if it is currently holding expected.
 * @return true if successful
 */
public final native boolean compareAndSwapLong(Object o, long offset, long expected, long x);

我们以其中的compareAndSwapInt为例,来说明

compareAndSwapInt

  • 方法作用:如果当前时刻,待更新的原值 与 预期值 expected相等,则将 待更新的原值 的 值更新 为x。如果更新成功,则返回 true,否则返回 false。
  • compareAndSwapInt是 Unsafe 类中提供的一个原子操作。方法一共有四个参数: 1.o:需要改变的对象 2.offset:内存偏移量,offset 为o对象所属类中,某个属性在类中的内存地址偏移量 3.expected :预期值 4.x:拟替换的新值

内存偏移量offset的作用是什么?

  • 计算出对象中,待更新的原值的准确内存地址
  • Java对象在内存中会占用一段内存区域,Java对象的属性会按照一定的顺序在对象内存中存储。根 据对象this就可以定位到this对象在内存的起始地址,然后在根据属性state(相对this)的offset内存 偏移量,就可以精确的定位到state的内存地址,从而得到当前时刻state在内存中的值。

在这里插入图片描述 在这里插入图片描述

2.4 CAS缺陷

CAS虽然高效地解决了原子操作,但是还是存在一些缺陷的,主要表现在三个地方:循环时间太长、只能保证一个共享变量原子操作、ABA问题。

  • 循环时间太长:如果CAS一直不成功呢?如果自旋CAS长时间地不成功,则会给CPU带来非常大的开销。 原子类AtomicInteger#getAndIncrement()的方法
  • 只能保证一个共享变量原子操作:看了CAS的实现就知道这只能针对一个共享变量,如果是多个共 享变量就只能使用锁了。
  • ABA问题:CAS需要检查操作值有没有发生改变,如果没有发生改变则更新。但是存在这样一种情 况:如果一个值原来是A,变成了B,然后又变成了A,那么在CAS检查的时候会发现没有改变,但 是实质上它已经发生了改变,这就是所谓的ABA问题。对于ABA问题其解决方案是加上版本号,即 在每个变量绑定一个版本号,每次改变时加1,即A —> B —> A,变成1A —> 2B —> 3A。

下面我们将通过一个例子可以可以看到AtomicStampedReference和AtomicInteger的区别。我们定义 两个线程,线程1负责将100 —> 101 —> 100,线程2执行 100 —>2022,看两者之间的区别。 在这里插入图片描述 在这里插入图片描述 运行结果充分展示了AtomicInteger的ABA问题和AtomicStampedReference解决ABA问题。在这里插入图片描述

标签:JUC,Java,CAS,原子,并发,int,内存,expected
From: https://blog.51cto.com/u_15323027/9585904

相关文章

  • 阿里面试:设计一个大并发、大数据的系统架构,说说设计思路
    文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录博客园版为您奉上珍贵的学习资源:免费赠送:《尼恩Java面试宝典》持续更新+史上最全+面试必备2000页+面试必备+大厂必备+涨薪必备免费赠送:《尼恩技术圣经+高并发系列PDF》,帮你实现技术自由,完成职业升级,薪......
  • synchronized【如何保证原子性、可见性、有序性】【如何实现原子性 原理解析】【什么
    @TOC转自极客时间如何解决可见性问题?同步原理剖析什么是Monitor?什么是锁优化?......
  • 【APP自动化进阶】pytest+appium多设备并发
    并发编程基础【Python进阶】并发编程方式APP自动化并发项目实战项目步骤获取设备信息并根据设备数量开启n个进程appium服务处理pytest前置处理开启appium服务pytest后置处理关闭appium服务pytest进行用例执行,并输出报告数据等待进程执行完毕生成每个设备的allure报告......
  • go并发编程
    go的GMP并发模型,让go天然支持高并发,先了解一下GMP模型吧GMPG协程,M工作线程、P处理器,M必须持有P才可以执行GP维护着一个协程G队列,P依次将G调度到M中运行ifM0中G0发生系统调用,M0将释放P,冗余的M1获取P,继续执行P队列中剩余的G。(只要P不空闲就充分利用了CPU)G0系统调用结束后,如果......
  • 【Python进阶】并发编程方式
    并发编程方式有哪些?threading模块---线程asyncio模块---协程concurrent.futures模块---进程+线程(应用于异步调用)multiprocessing模块---进程进程、线程、协程?进程:运行起来的程序就是进程,是操作系统分配资源的最小单位。线程:线程是进程的组成部分,一个进程可以拥有多个线......
  • Java并发基础:CountDownLatch全面解析!
    内容概要CountDownLatch的优点在于能够简洁高效地协调多个线程的执行顺序,确保一组线程都完成后才触发其他线程的执行,适用于资源加载、任务初始化等场景。它提供了清晰的等待/通知机制,易于理解和使用,是提升多线程程序性能和可靠性的重要工具。核心概念CountDownLatch是java.util......
  • 参数调优 -- 并发参数innodb_thread_concurrency
    innodb_thread_concurrencyinnodb_thread_concurrency是动态参数可以随时修改64个活跃连接以内直接配0高压场景需要从高到低测试,找到最优值高压场景下较低的值可以明显提高写入QPS的占比(高频率的读被限制了)innodb_thread_sleep_delay(微秒)定义在开始排队前,等多久加入队列innodb_......
  • Java并发基础:CyclicBarrier全面解析!
    内容摘要CyclicBarrier的优点在于实现了线程间的相互等待与协同,确保所有线程在达到预定屏障点后才能继续执行,它支持屏障的重复使用,非常适合多轮次的任务同步,此外,CyclicBarrier还允许在屏障点执行特定操作,为复杂的多线程协作提供了便利。核心概念业务场景CyclicBarrier允许一组......
  • Java并发基础:Phaser全面解析!
    内容概要Phaser是Java中一个灵活的同步工具,其优点在于支持多阶段的任务拆分与同步,并且能够动态地注册与注销参与者,它提供了丰富的等待与推进机制,使得开发者能够更细粒度地控制线程的协调行为,实现复杂的并行任务处理,相比于其他同步工具,Phaser更加灵活且易于扩展,适用于多种并发场景......
  • 火山引擎ByteHouse:分析型数据库如何设计并发控制?
    更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群分析型数据库设计并发控制的主要原因是为了确保数据的完整性和一致性,同时提高数据库的吞吐量和响应速度。并发控制可以防止多个事务同时对同一数据进行修改,导致数据不一致的情况发生。通过合......