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
接下来进行深入研究:
AtomicInteger i = new AtomicInteger(0);
private void incr(){
i.incrementAndGet();//对变量加1操作,并返回(原子操作)
}
public class AtomicInteger extends Number implements java.io.Serializable {
private static final Unsafe unsafe = Unsafe.getUnsafe();
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
}
public final class Unsafe {
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);//先获取期望值
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
//如果比较和交换失败,就会一直重试,直到成功位置
return var5;
}
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
}
在这里我们看到了Unsafe类,它在 package sun.misc 目录下面,并不在SDK中。
Unsafe是一个功能强大的类,它可以像C/C++一样 直接操作对象内存,修改jvm运行时的数据,它的操作粒度不是类,而是直接针对数据和地址,有点类似于C/C++中的指针。
我们在23行看到了CAS,就是 compareAndSwapInt() 方法,它是一个本地方法,我们无法再深入看下去。
1.5 详细解析CAS
CAS是英文单词Compare And Swap的缩写,翻译过来就是比较并替换。
CAS机制当中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B。
更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。
这样说或许有些抽象,我们来看一个例子:
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
最后
我见过很多技术leader在面试的时候,遇到处于迷茫期的大龄程序员,比面试官年龄都大。这些人有一些共同特征:可能工作了7、8年,还是每天重复给业务部门写代码,工作内容的重复性比较高,没有什么技术含量的工作。问到这些人的职业规划时,他们也没有太多想法。
其实30岁到40岁是一个人职业发展的黄金阶段,一定要在业务范围内的扩张,技术广度和深度提升上有自己的计划,才有助于在职业发展上有持续的发展路径,而不至于停滞不前。
不断奔跑,你就知道学习的意义所在!
以上进阶BATJ大厂学习资料可以免费分享给大家,需要完整版的朋友,【点这里可以看到全部内容】。
试官年龄都大。这些人有一些共同特征:可能工作了7、8年,还是每天重复给业务部门写代码,工作内容的重复性比较高,没有什么技术含量的工作。问到这些人的职业规划时,他们也没有太多想法。
其实30岁到40岁是一个人职业发展的黄金阶段,一定要在业务范围内的扩张,技术广度和深度提升上有自己的计划,才有助于在职业发展上有持续的发展路径,而不至于停滞不前。
不断奔跑,你就知道学习的意义所在!
以上进阶BATJ大厂学习资料可以免费分享给大家,需要完整版的朋友,【点这里可以看到全部内容】。