推荐 7 个学习 TypeScript 的宝库
这里我们发现 log.info("execute");,在代码中只执行了一次,并且 isHappened:true的值为true,这是为啥呢? 这里是因为当程序第一次 compareAndSet()的时候,使得 isHappend变为了true,因为原子性的关系,没有其他线程进行干扰,通过使用AtomicBoolean,我们使某段代码只执行一次。 3.1.4、AtomicReference AtomicReference和 AtomicInteger非常类似,不同之处就在于 AtomicInteger是对整数的封装,底层采用的是 compareAndSwapInt实现CAS,比较的是数值是否相等,而 AtomicReference则对应普通的对象引用,底层使用的是 compareAndSwapObject实现CAS,比较的是两个对象的地址是否相等。也就是它可以保证你在修改对象引用时的线程安全性。
多个线程之间的操作无论采用何种执行时序或交替方式,都要保证不变性条件不被破坏,要保持状态的一致性,就需要在单个原子操作中更新相关的状态变量。 分析: 如果你的日志中搜不到上面信息,说明你的注解处理器没有被添加到javac的 classpath 中。一般问题就是你的META-INF/services/javax.annotation.processing.Processor声明有问题,javac无法找到你的注解处理器。有些同学可能是通过 google 的 AutoService 来生成META-INF/services/javax.annotation.processing.Processor的,这种情况下也要自己检查是否 OK(譬如之前安卓中 AGP 有一段时间的中间过渡版本就修改了 classpath,需要手动将 compile 改成 annotationProcessor 才行)。
2.在你的日志中搜索Round关键字,建议直接搜Round 1:这样的格式容易点,看到的日志会是如下。 添加上面参数后一定要将你的构建日志追加到一个磁盘文件中,因为日志会变得非常庞大,同时也变得很容易定位问题。 通过构建日志分析定位问题 执行你的构建任务,完毕后分析定位主要分为如下几个步骤,每一步都是一种场景的定位,循序渐进定位分析即可。
1.在你的日志中搜索你的 Processor 类名,譬如TestAnnotationProcessor.class,看到的日志会是如下。 我们可以看到 getAndAddInt(Objectvar1,longvar2,intvar4),传进来的第一个参数是当前的一个对象,也就是我们的:count.incrementAndGet(),在 getAndAddInt()中,var1就是count,var2就是当前的值,比如当前循环中count值为 2,var4为每次递增1 其次 getAndAddInt()方法中涉及到的两个方法调用都定义为native,即java底层实现的本地方法
我们知道 volatile具有一致性的特征,但是它不具备原子性,为什么 AtomicInteger却同时具备一致性和原子性,原来在 AtomicInteger源码中实现了这样一串代码:privatevolatileintvalue;,在 AtomicInteger内部实现就使用了 volatile关键字,这就是为什么执行CAS(对CAS有疑问的点击此处)操作的时候,从底层获取的数据就是最新的数据:
使用 AtomicInteger的好处在于,它不同于 sychronized关键字或 lock用锁的形式来实现原子性,加锁会影响性能,而是采用循环比较的形式来提高性能。 3.1.2、AtomicLong
AtomicLong 是作用是对长整形进行原子操作,依靠底层的cas来保障原子性的更新数据,在要添加或者减少的时候,会使用死循环不断地cas到特定的值,从而达到更新数据的目的。 (编辑:惠州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |