CAS机制详解,跨平台移动开发

1.2、什么是原子操作?

1.3、JDK中相关原子操作类

1.3.1、原子更新基本类型,

1.3.2、原子更新数组类型

1.3.3、原子更新引用类型

1.3.4、原子更新字段类

1.4、优化Demo2

1.5 详细解析CAS


相关文章:

=====

java高并发:CAS无锁原理及广泛应用(2w阅读量)

漫画:什么是 CAS 机制?(漫画版,深入浅出)

漫画:什么是CAS机制?(进阶篇)(Java语言CAS底层如何实现、什么是ABA问题?怎么解决?)

一、什么是CAS?

=========

具体可看  漫画:什么是 CAS 机制?

Atomic操作类的底层,正是利用了我们所说的CAS机制

CAS是英文单词Compare And Swap的缩写,翻译过来就是比较并替换。

CAS(V,E,N) 机制当中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B。

更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。

先来实现一段代码

1.1、Demo1


public class Demo1 {

int i = 0;

public void incr() {

i++;//加1操作

}

public static void main(String[] args)throws Exception {

Demo1 demo1 = new Demo1();

for (int j = 0; j < 2; j++) {//new 两个线程

new Thread(new Runnable() {

@Override

public void run() {

for (int k = 0; k < 10000; k++) {//每个线程执行10000遍

demo1.incr();

}

}

}).start();

}

Thread.sleep(1000);

System.out.println(demo1.i);//打印结果是否为20000?

}

}

打印结果:

可能是20000,更多的是小于20000的整数,

运行多次后可以看到,打印结果是小于200

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

00的。为什么会出现这样的结果呢?

这是因为 incr() 方法中的 i++ 操作不是原子性的,这就意味这它会被干扰。

在IDEA中,我们使用Show ByteCode(反编译字节码)看它的字节码文件:

再来看 incr() 方法中的 i++  它实际上被分成了多步操作,因此不具备原子性

private incr()V

L0

LINENUMBER 7 L0

ALOAD 0

DUP

GETFIELD com/ph/cas/Demo1.i : I //获取字段值

ICONST_1

IADD //相加

PUTFIELD com/ph/cas/Demo1.i : I //赋值

L1

LINENUMBER 8 L1

RETURN

L2

LOCALVARIABLE this Lcom/ph/cas/Demo1; L0 L2 0

MAXSTACK = 3

MAXLOCALS = 1

1.2、什么是原子操作?


原子操作可以是一个步骤,也可以是多个步骤,但是其顺序不可以被打乱,也不可以被切割而只执行其中的一部分(不可中断性)。将整个操作视作一个整体是原子性的核心特征。

1.3、JDK中相关原子操作类


1.3.1、原子更新基本类型,

Atomic包提供了以下3个类。·AtomicBoolean AtomicInteger  AtomicLong。

1.3.2、原子更新数组类型

AtomicIntegerArray:原子更新整型数组里的元素。

AtomicLongArray:原子更新长整型数组里的元素。

·AtomicReferenceArray:原子更新引用类型数组里的元素。

1.3.3、原子更新引用类型

AtomicReference:原子更新引用类型。

AtomicMarkableReference,AtomicStampeReference

1.3.4、原子更新字段类

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

AtomicIntegerFiledUpdater,AtomicLongFiledUpdater

下面我们对Demo1进行优化:

1.4、优化Demo2


public class Demo2 {

AtomicInteger i = new AtomicInteger(0);

private void incr(){

i.incrementAndGet();//对变量加1操作,并返回(原子操作)

}

public static void main(String[] args)throws Exception {

Demo2 demo2 = new Demo2();

for (int j = 0; j < 2; j++) {//new 两个线程

new Thread(new Runnable() {

@Override

public void run() {

for (int k = 0; k < 10000; k++) {//每个线程执行10000遍

demo2.incr();

}

}

}).start();

}

Thread.sleep(1000);

System.out.println(demo2.i);//打印结果是否为20000?

}

}

打印结果:20000

我们来看 inrc() 的字节码文件:

private incr()V

L0

LINENUMBER 10 L0

ALOAD 0

GETFIELD com/ph/test/Demo2.i : Ljava/util/concurrent/atomic/AtomicInteger;

INVOKEVIRTUAL java/util/concurrent/atomic/AtomicInteger.incrementAndGet ()I

POP

接下来进行深入研究:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值