AtomicInteger 源码阅读
Package java.util.concurrent.atomic
这是一个小工具包,它的实际作用是提供了很多个无阻塞的线程安全的变量操作工具。
无阻塞的线程安全:其含义就是不使用 synchronize,而使用 volatile+CAS 的方式实现。
该包下类摘要
挑一个 AtomicInteger 来分析一下吧,比较典型。
package java.util.concurrent.atomic;import java.util.function.IntUnaryOperator;import java.util.function.IntBinaryOperator;import sun.misc.Unsafe;
/** * 原子性地更新int类型地值。 * java.util.concurrent.atomic * AtomicInteger 常用于原子地计数器中,并且不能用于替代Integer。 */public class AtomicInteger extends Number implements java.io.Serializable { private static final long serialVersionUID = 6214790243416807050L;
// 设置使用Unsafe.compareAndSwapInt来进行更新, cas操作 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); } }
// 存放值的地方, 用了volatile修饰 private volatile int value;
/** * 创建一个给定初始值的AtomicInteger对象 */ public AtomicInteger(int initialValue) { value = initialValue; }
/** * 创建一个初始值为0的AtomicInteger对象 */ public AtomicInteger() { }
/** * 获取当前的值, 这里也没有加锁 * 只要别人update了, volatile一定会让你看到 */ public final int get() { return value; }
/** * 设定新的值, 看看这里也没有加锁 * 只要别人update了, volatile一定会让你看到 */ public final void set(int newValue) { value = newValue; }
/** * 最终会设置成newValue,使用lazySet设置值后,可能导致其他线程在之后的一小段时间内还是可以读到旧的值。 */ 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); }
/** * 以原子方式将当前值加1,注意:这里返回的是自增前的值。 */ public final int getAndIncrement() { return unsafe.getAndAddInt(this, valueOffset, 1); }
/** * 以原子方式将当前值减1,注意:这里返回的是自增前的值。 */ public final int getAndDecrement() { return unsafe.getAndAddInt(this, valueOffset, -1); }
/** * 以原子方式将当前值加上给定的值,注意:这里返回的是自增前的值。 */ public final int getAndAdd(int delta) { return unsafe.getAndAddInt(this, valueOffset, delta); }
/** * 以原子方式将当前值加1,注意:这里返回的是增加后的值。 */ public final int incrementAndGet() { return unsafe.getAndAddInt(this, valueOffset, 1) + 1; }
/** * 以原子方式将当前值减1,注意:这里返回的是减少后的值。 */ public final int decrementAndGet() { return unsafe.getAndAddInt(this, valueOffset, -1) - 1; }
/** * 以原子方式将输入的数值与实例中的值(AtomicInteger里的value)相加 * 并返回更新后的结果 */ public final int addAndGet(int delta) { return unsafe.getAndAddInt(this, valueOffset, delta) + 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 updateAndGet(IntUnaryOperator updateFunction) { int prev, next; do { prev = get(); next = updateFunction.applyAsInt(prev); } while (!compareAndSet(prev, next)); return next; }
/** * 你爱干啥干啥 */ 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 accumulateAndGet(int x, IntBinaryOperator accumulatorFunction) { int prev, next; do { prev = get(); next = accumulatorFunction.applyAsInt(prev, x); } while (!compareAndSet(prev, next)); return next; }
/** * 返回当前值的字符串表示 */ public String toString() { return Integer.toString(get()); }
/** * 返回当前值的整数 */ public int intValue() { return get(); }
/** * 返回当前值的整数形式 */ public long longValue() { return (long)get(); }
/** * 返回当前值的单精度浮点形式 */ public float floatValue() { return (float)get(); }
/** * 返回当前数双精度浮点形式 */ public double doubleValue() { return (double)get(); }
}
大部分都还是看得懂的,但是有几个方法是有疑惑的:
public final boolean weakCompareAndSet(int expect, int update);
public final void lazySet(int newValue);
这两个是干啥用的?
下面该看一下 Unsafe 的工作原理了。
AtomicInteger 源码阅读的更多相关文章
- JDK1.8源码阅读笔记(2) AtomicInteger AtomicLong AtomicBoolean原子类
JDK1.8源码阅读笔记(2) AtomicInteger AtomicLong AtomicBoolean原子类 Unsafe Java中无法直接操作一块内存区域,不能像C++中那样可以自己申请内存 ...
- 应用监控CAT之cat-client源码阅读(一)
CAT 由大众点评开发的,基于 Java 的实时应用监控平台,包括实时应用监控,业务监控.对于及时发现线上问题非常有用.(不知道大家有没有在用) 应用自然是最初级的,用完之后,还想了解下其背后的原理, ...
- ThreadPoolExecutor 源码阅读
目录 ThreadPoolExecutor 源码阅读 Executor 框架 Executor ExecutorService AbstractExecutorService 构造器 状态 Worke ...
- guavacache源码阅读笔记
guavacache源码阅读笔记 官方文档: https://github.com/google/guava/wiki/CachesExplained 中文版: https://www.jianshu ...
- 【原】FMDB源码阅读(三)
[原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...
- 【原】FMDB源码阅读(二)
[原]FMDB源码阅读(二) 本文转载请注明出处 -- polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比 ...
- 【原】FMDB源码阅读(一)
[原]FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于 ...
- 【原】AFNetworking源码阅读(六)
[原]AFNetworking源码阅读(六) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这一篇的想讲的,一个就是分析一下AFSecurityPolicy文件,看看AF ...
- 【原】AFNetworking源码阅读(五)
[原]AFNetworking源码阅读(五) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中提及到了Multipart Request的构建方法- [AFHTTP ...
随机推荐
- Ubuntu python Compression requires the (missing) zlib module
描述: 在Ubuntu中安装setuptools时出现 Compression requires the (missing) zlib module 解决方法步骤: ①Ubuntu下安装zlib: ...
- Web前端性能优化进阶——完结篇
前言 在之前的文章 如何优化网站性能,提高页面加载速度 中,我们简单介绍了网站性能优化的重要性以及几种网站性能优化的方法(没有看过的可以狂戳 链接 移步过去看一下),那么今天我们深入讨论如何进一步优化 ...
- Python3练习题系列(07)——列表操作原理
目标: 理解列表方法的真实含义. 操作: list_1.append(element) ==> append(list_1, element) mystuff.append('hello') 这 ...
- Java并发程序设计(七)乐天派:无锁
无锁 一.概述 无锁是处理并发的一种乐观策略,它会假设对资源的访问是没有冲突的.既然没有冲突自然不需要等待,所以所有的线程都可以在不停顿的状态下执行.那遇到冲突怎么办?接下来请看,无锁绝招“CAS”即 ...
- CAD画图技巧经验
1.CAD中如何输入特殊符号 %% d ——绘制“℃”符号.例如: 98.6 ℃—— 98.6 %% dC : %% c ——绘制圆直径“φ”符号.例如:φ 30 ——%% c30 : %% p —— ...
- 搜索+剪枝——POJ 1011 Sticks
搜索+剪枝--POJ 1011 Sticks 博客分类: 算法 非常经典的搜索题目,第一次做还是暑假集训的时候,前天又把它翻了出来 本来是想找点手感的,不想在原先思路的基础上,竟把它做出来了而且还是0 ...
- BZOJ3682 Phorni 后缀平衡树
后缀平衡树的裸题 后缀平衡树简单的思想如下 具体的可以去看$clj$的论文 假设我们已经有了串$S$的后缀平衡树 插入一个字母$c$ 我们用$Si$代表原串$S$从第$i$个字符开始的后缀 则后缀$c ...
- 429. N叉树的层序遍历
429. N叉树的层序遍历 题意 给定一个 N 叉树,返回其节点值的层序遍历. (即从左到右,逐层遍历). 解题思路 和二叉树的层次遍历的思想一样: 实现 class Solution(object) ...
- C# abstract virtual override new finally java final finalize
virtual:声明虚方法.可以被其派生类所重写的.重写方法需要使用override或者new关键字. override:覆盖原方法.可对重写virtual.override.abstract进行重写 ...
- Using a Virtex Device to Drive 5V CMOS-Level Signals
Must tri-state outputs and use an external resistor to pull up to 5V To drive 5V CMOS-level inputs, ...