![](https://img.haomeiwen.com/i10107787/6d8f0b818c76beba.png)
点赞关注,不再迷路,你的支持对我意义重大!
🔥 Hi,我是丑丑。本文 「Java 路线」导读 —— 他山之石,可以攻玉 已收录,这里有 Android 进阶成长路线笔记 & 博客,欢迎跟着彭丑丑一起成长。(联系方式在 GitHub)
前言
目录
![](https://img.haomeiwen.com/i10107787/da1366db7539e0d2.png)
前置知识
这篇文章的内容会涉及以下前置 / 相关知识,贴心的我都帮你准备好了,请享用~
-
并发编程: 「Java 路线」| 并发编程的基础概念
2. 什么是原子操作?
原子操作(atomic operation)指:不可被分割的一个或一系列操作。在 Java 中,可以使用「锁」和 「自旋 CAS」来实现原子操作。
Editting...
3. CAS 存在的问题
3.1 ABA 问题:无法感知 ABA 的修改过程
在 CAS 操作中,会检查值是否符合预期值,符合则认为没有被修改过。但如果这个值原来是「A」,被修改为「B」,又被改为「A」,CAS 操作时无法感知的。
解决思路是增加时间戳或版本号,例如 JDK 1.5 中就提供了 AtomicMarkableReference(带更新标志位)和 AtomicStampedReference(带版本号),这些类的 CAS 操作除了检查值是否符合预期外,还会检查当前「标志位 / 版本号」是否也符合预期,这样就解决了 ABA 问题。
3.2 开销问题:长时间自旋开销大
在锁资源竞争紧张的情况下,会导致自旋 CAS 会长时间不成功,增大了 CPU 负载。
3.3 只能保证一个变量的原子操作
对一个变量进行 自旋 CAS 操作时,可以保证原子性。但如果对多个变量进行操作时,自旋 CAS 就无法保证原子性。
解决思路是将多个变量合并为一个变量,例如 JDK 1.5 中就提供了 AtomicReference 来保证引用对象之间的原子性。
public static AtomicReference<User> atomicUserRef = new AtomicReference<>();
User user = new User("peng", 0);
atomicUserRef.set(user)
User newUser = new User("xurui", 1);
atomicUserRef.compareAndSet(user, newUser);
4. 原子操作类
从 JDK 1.5 开始,Java 提供了一系列原子操作类,具体可以划分为以下四种:
4.1 基本类型
- AtomicBoolean
- AtomicInteger
- AtomicLong
4.2 数组
- AtomicIntegerArray
- AtomicLongArray
- AtomicReferenceArray
4.3 引用
- AtomicReference
- AtomicMarkableReference(带更新标志位)
- AtomicStampedReference(带版本号)
4.4 字段
- AtomicIntegerFieldUpdater
- AtomicLongFieldUpdater
- AtomicReferenceFieldUpdater
5. 总结
- CAS 实现原子操作存在三大问题,即:「ABA 问题:无法感知 ABA 的修改过程」、「开销问题:长时间自旋开销大」和「只能保证一个变量的原子操作」;
- 从 JDK 1.5 开始,Java 提供了一系列原子操作类。
创作不易,你的「三连」是丑丑最大的动力,我们下次见!
![](https://img.haomeiwen.com/i10107787/8a6d3a74f22bec02.png)
网友评论