JDK7中AtomicInteger源码解析
来源:互联网 发布:linux语言包大全 编辑:程序博客网 时间:2024/06/07 14:58
虽然Atomic*原子类在JDK7和JDK8中很多方法的实现是存在差异的,但是都是采用无锁编程CAS实现,其底层实现由Unsafe类提供更新与实现。
1.Unsafe类概述
Java不能直接访问操作系统底层,而是通过Native本地方法来访问。Unsafe类提供了硬件级别的原子操作,主要提供了以下功能:
(a)通过Unsafe类可以分配内存,可以释放内存;
类中提供的3个本地方法allocateMemory、reallocateMemory、freeMemory分别用于分配内存,扩充内存和释放内存。
(b)可以定位对象某字段的内存位置,也可以修改对象的字段值,即使它是私有的
JAVA中对象的字段的定位可能通过staticFieldOffset方法实现,该方法返回给定field的内存地址偏移量,这个值对于给定的filed是唯一的且是固定不变的。
(c)挂起与恢复
将一个线程进行挂起是通过park方法实现的,调用park后线程将一直阻塞直到超时或者中断等条件出现,unpark可以终止一个挂起的线程使其恢复正常。
(d)CAS操作
通过compareAndSwapXXX方法实现的。
Note:CAS会存在“ABA”问题,AtomicStampedReference/AtomicMarkableReference提供的版本控制机制可以有效的解决这个“ABA”问题但是效率不高(未测试是否准确?)。
2.AtomicInteger类概述
public class AtomicInteger extends Number implements java.io.Serializable;
// AtomicInteger只有3个成员变量
private static final Unsafe unsafe = Unsafe.getUnsafe(); // 用来实现CAS
private static final long valueOffset; // value值在内存地址中的偏移量
static { // 获取value值偏移量地址
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
private volatile int value; // AtomicInteger对应的值
AtomicInteger提供了两个构造函数,如下所示:
(a)AtomicInteger() // 创建具有初始值0的新AtomicInteger
(b)AtomicInteger(int initialValue){
value = initialValue; // 创建具有给定初始值的新AtomicInteger
}
3. AtomicInteger重要方法分析
AtomicInteger虽然提供了不少实现方法,但其中最重要的方法是:自增(减),两数相加,以及initValue();像其它的获取值,设置值和以某种形式返回值(继承Number类的实现方法)等方法都是辅助手段(个人理解)。由于此处实现方法类似,故只用自增和两数相加进行源码解析:
public final int getAndIncrement() {
for (;;) { // 此处自旋,由JVM处理自旋多久
int current = get(); // 获取当前value值
int next = current + 1; // 设置新值
if (compareAndSet(current, next))
return current; // CAS实现值的更新,当前值==期望值就更新为新值
}
}
public final int incrementAndGet() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
由源码可以看出getAndIncrement和incrementAndGet两者的实现差异只是返回值不同,此处的实现差异类似i++和++i。此处decrementAndGet和getAndDecrement实现方法类似自增,只是next的取值是:current-1。
public final int getAndAdd(int delta) {
for (;;) {
int current = get();
int next = current + delta;
if (compareAndSet(current, next))
return current;
}
}
public final int addAndGet(int delta) {
for (;;) {
int current = get();
int next = current + delta;
if (compareAndSet(current, next))
return next;
}
}
由源码可以看出此处的实现类似getAndIncrement和incrementAndGet,只是这里把自增的值替换为传入的delta值。
public int intValue() {
return get(); // 返回value值
}
Note:继承Number类,实现以什么形式返回值,只需要将返回值进行强行转换即可,例如以long形式的返回:(long)get()。
public final int get() {
return value;
}
// CAS更新值,当前值==期望值则返回更新的值
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);
}
Note:同compareAndSet相比会错误的失败,并且不保证排序,表示不理解?
public final void lazySet(int newValue) {
unsafe.putOrderedInt(this, valueOffset, newValue);
}
Note:putOrderedInt值是立即写回主存还是不立即写回主存,按顺序写回主存?
实现总结:AtomicInteger的功能实现比较简单,基本都是使用Unsafe的CAS无锁编程实现,首先获取到value值,然后进行计算后得到新值,最后使用CAS进行内存更新。此类有多处需要注意的地方:使用自旋实现内存更新,在设值和计算的时候有++i(Get在后面)和i++的区别,除了两数相加和自增以外没有提供其它的操作,可直接使用CAS来更新value值。
- JDK7中AtomicInteger源码解析
- JDK7中LockSupport源码解析
- JDK7中ArrayBlockingQueue源码解析
- JDK7中LinkedBlockingQueue源码解析
- JDK7中SynchronousQueue源码解析
- AtomicInteger源码解析
- CAS AtomicInteger 源码解析
- AtomicInteger源码解析
- JDK7中StringBuffer/StringBuilder源码解析
- JDK7中ReentrantLock源码解析(1)
- JDK7中ReentrantLock源码解析(2)
- JDK7中ReentrantLock源码解析(3)
- JDK7中ReentrantReadWriteLock源码解析(1)
- JDK7中ReentrantReadWriteLock源码解析(2)
- JDK7中ReentrantReadWriteLock源码解析(3)
- JDK 源码解析 —— AtomicInteger
- JDK7中Condition源码概述
- JDK7中Lock源码概述
- Kotlin学习资料整合
- 关于token的个人理解(个人)
- PAT刷题:1050. 螺旋矩阵(25)
- 第八章函数十个问题及解答
- Linux环境下IO多路复用
- JDK7中AtomicInteger源码解析
- 【React Native开发】React Native进行签名打包成Apk
- 常见知识点
- Java爬取网页图片
- JS forEach 用法
- 统计学习方法-第二章-感知机
- ListView的实际案例操作和解析
- BZOJ4719 &&NOIP2016 天天爱跑酷
- 1024,千家公司程序员幸福指数大比拼!最“幸福”的程序员是你吗?