Atomic 原子类详细介绍

Atomic 原子类详细介绍

Atomic 翻译成中文是原子的意思。在化学上,我们知道原子是构成一般物质的最小单位,在化学反应中是不可分割的。在我们这里 Atomic 是指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰。所以,所谓原子类说简单点就是具有原子/原子操作特征的类。并发包 java.util.concurrent 的原子类都存放在 java.util.concurrent.atomic 下,如下图所示。

根据操作的数据类型,可以将JUC包中的原子类分为4类

基本类型

使用原子的方式更新基本类型

AtomicInteger:整型原子类

AtomicLong:长整型原子类

AtomicBoolean :布尔型原子类

数组类型

使用原子的方式更新数组里的某个元素

AtomicIntegerArray:整型数组原子类

AtomicLongArray:长整型数组原子类

AtomicReferenceArray :引用类型是数组原子类

引用类型

AtomicReference:引用类型原子类

AtomicMarkableReference:原子更新带有标记的引用类型。该类将 boolean 标记与引用关联起来,也可以解决使用 CAS 在进行原子更新时可能出现的 ABA 问题。

AtomicStampedReference :原子更新带有版本号的引用类型。该类将整数值与引用关联起来,可用于解决原子的更新数据和数据的版本号,可以解决使用 CAS 进行原子更新时可能出现的 ABA问题。

对象的属性修改类型

AtomicIntegerFieldUpdater:原子更新整型字段的更新器

AtomicLongFieldUpdater:原子更新长整型字段的更新器

AtomicReferenceFieldUpdater:原子更新引用类型里的字段

修正: AtomicMarkableReference 不能解决ABA问题

/**AtomicMarkableReference是将一个boolean值作是否有更改的标记,本质就是它的版本号只有两个,true和false,修改的时候在这两个版本号之间来回切换,这样做并不能解决ABA的问题,只是会降低ABA问题发生的几率而已

*/

public class SolveABAByAtomicMarkableReference {

private static AtomicMarkableReference atomicMarkableReference = new

AtomicMarkableReference(100, false);

public static void main(String[] args) {

Thread refT1 = new Thread(() -> {

try {

TimeUnit.SECONDS.sleep(1);

} catch (InterruptedException e) {

e.printStackTrace();

}

atomicMarkableReference.compareAndSet(100, 101,

atomicMarkableReference.isMarked(), !atomicMarkableReference.isMarked());

atomicMarkableReference.compareAndSet(101, 100,

atomicMarkableReference.isMarked(), !atomicMarkableReference.isMarked());

});

Thread refT2 = new Thread(() -> {

boolean marked = atomicMarkableReference.isMarked();

try {

TimeUnit.SECONDS.sleep(2);

} catch (InterruptedException e) {

e.printStackTrace();

}

boolean c3 = atomicMarkableReference.compareAndSet(100, 101,

marked, !marked);

System.out.println(c3); // 返回true,实际应该返回false

});

refT1.start();

refT2.start();

}

}

CAS ABA 问题

描述: 第一个线程取到了变量 x 的值 A,然后巴拉巴拉干别的事,总之就是只拿到了变量 x 的值A。这段时间内第二个线程也取到了变量 x 的值 A,然后把变量 x 的值改为 B,然后巴拉巴拉干别的事,最后又把变量 x 的值变为 A (相当于还原了)。在这之后第一个线程终于进行了变量 x 的操作,但是此时变量 x 的值还是 A,所以 compareAndSet 操作是成功。例子描述(可能不太合适,但好理解): 年初,现金为零,然后通过正常劳动赚了三百万,之后正常消费了(比如买房子)三百万。年末,虽然现金零收入(可能变成其他形式了),但是赚了钱是事实,还是得交税的!

代码例子(以 AtomicInteger 为例)

【关注】转发了解更多内容,方便后续查看

郑重声明:本文内容及图片均整理自互联网,不代表本站立场,版权归原作者所有,如有侵权请联系管理员(admin#wlmqw.com)删除。
(0)
用户投稿
上一篇 2022年7月5日
下一篇 2022年7月5日

相关推荐

联系我们

联系邮箱:admin#wlmqw.com
工作时间:周一至周五,10:30-18:30,节假日休息