java源码-AtomicInteger
开篇
AtomicInteger位于java.util.concurrent.atomic包下,是java提供给的可以保证数据的原子性操作的一个类。
Atomicxxxx系列主要核心在于Unsafe这个类的运用保证线程安全,而Unsafe这个类应该是通过JNI调用的底层实现。
关于unsafe类可以看看揭秘sun.misc.Unsafe,虽然我还是没怎么看懂。记住unsafe这个东西很重要,不过据说在jdk9之后应该会被弃用了。
AtomicInteger类构造器
AtomicInteger类构造器有两个:
- 无参构造函数采用默认值初始化为0
- 有参数构造函数直接用initialValue来value的
- AtomicInteger的关键逻辑在于static代码快中通过unsafe接口初始化value的内存地址,后续直接通过内存地址进行操作。
另外我们需要注意到value是用volatile进行修饰保证变量的可见性,这个有空一定要仔细研究研究。
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
private volatile int value;
// value值初始化为initialValue
public AtomicInteger(int initialValue) {
value = initialValue;
}
// value的值为默认值为0
public AtomicInteger() {
}
}
AtomicInteger的get操作
AtomicInteger的get操作还是比较有意思的,总共非几大类:
- get()方法直接返回值
- getAndIncrement()、getAndDecrement()、getAndAdd()、getAndUpdate()先返回旧值后对旧值执行加减操作。
- incrementAndGet()、decrementAndGet()、addAndGet()、updateAndGet()先执行加减操作后返回新值。
- 底层操作unsafe.getAndAddInt()的实现细节借助于unsafe的compareAndSwapInt()方法保证只有在旧值为v的情况下才能更新为v+delta值。
public final int getAndAddInt(Object o, long offset, int delta) {
int v;
do {
v = getIntVolatile(o, offset);
} while (!compareAndSwapInt(o, offset, v, v + delta));
return v;
}
---------------------------------------------------------------
public final int get() {
return value;
}
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
public final int getAndDecrement() {
return unsafe.getAndAddInt(this, valueOffset, -1);
}
public final int getAndAdd(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta);
}
public final int getAndUpdate(IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get();
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(prev, next));
return prev;
}
public final int getAndAccumulate(int x,
IntBinaryOperator accumulatorFunction) {
int prev, next;
do {
prev = get();
next = accumulatorFunction.applyAsInt(prev, x);
} while (!compareAndSet(prev, next));
return prev;
}
---------------------------------------------------------------
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
public final int decrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
}
public final int addAndGet(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
}
public final int updateAndGet(IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get();
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(prev, next));
return next;
}
public final int accumulateAndGet(int x,
IntBinaryOperator accumulatorFunction) {
int prev, next;
do {
prev = get();
next = accumulatorFunction.applyAsInt(prev, x);
} while (!compareAndSet(prev, next));
return next;
}
AtomicInteger的set操作
AtomicInteger的set操作基本上也分为两大类:
- 直接set设置value值
- 通过unsafe的api接口实现原子性写操作
public final int getAndAddInt(Object o, long offset, int delta) {
int v;
do {
v = getIntVolatile(o, offset);
} while (!compareAndSwapInt(o, offset, v, v + delta));
return v;
}
------------------------------------------------------------------
public final void set(int newValue) {
value = newValue;
}
public final void lazySet(int newValue) {
unsafe.putOrderedInt(this, valueOffset, newValue);
}
public final int getAndSet(int newValue) {
return unsafe.getAndSetInt(this, valueOffset, newValue);
}
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
public final boolean weakCompareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
参考文章
揭秘sun.misc.Unsafe
非阻塞同步算法与CAS(Compare and Swap)无锁算法
为什么volatile不能保证原子性而Atomic可以?
彻底了解内存屏障

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
ArcGIS API for JavaScript4.x 之加载2D、3D地图
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gisdoer/article/details/81545607 ArcGIS API for JavaScript 之加载2D、3D地图 点击查看文章
-
下一篇
[剑指offer] 从尾到头打印链表
本文首发于我的个人博客:尾尾部落 题目描述 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。 解题思路 一种方法是利用栈来实现; 另外一种方法是利用三个指针把链表反转,关键是 r 指针保存断开的节点。 image 参考代码 /** * public class ListNode { * int val; * ListNode next = null; * * ListNode(int val) { * this.val = val; * } * } * */ import java.util.ArrayList; public class Solution { public ArrayList<Integer> printListFromTailToHead(ListNode listNode) { if(listNode == null) return new ArrayList<Integer>(); ListNode head = listNode; ListNode cur = listNode.next; while( cur!= nu...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Dcoker安装(在线仓库),最新的服务器搭配容器使用
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS8编译安装MySQL8.0.19
- MySQL数据库在高并发下的优化方案
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池