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 源码阅读的更多相关文章

  1. JDK1.8源码阅读笔记(2) AtomicInteger AtomicLong AtomicBoolean原子类

    JDK1.8源码阅读笔记(2) AtomicInteger AtomicLong AtomicBoolean原子类 Unsafe Java中无法直接操作一块内存区域,不能像C++中那样可以自己申请内存 ...

  2. 应用监控CAT之cat-client源码阅读(一)

    CAT 由大众点评开发的,基于 Java 的实时应用监控平台,包括实时应用监控,业务监控.对于及时发现线上问题非常有用.(不知道大家有没有在用) 应用自然是最初级的,用完之后,还想了解下其背后的原理, ...

  3. ThreadPoolExecutor 源码阅读

    目录 ThreadPoolExecutor 源码阅读 Executor 框架 Executor ExecutorService AbstractExecutorService 构造器 状态 Worke ...

  4. guavacache源码阅读笔记

    guavacache源码阅读笔记 官方文档: https://github.com/google/guava/wiki/CachesExplained 中文版: https://www.jianshu ...

  5. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  6. 【原】FMDB源码阅读(二)

    [原]FMDB源码阅读(二) 本文转载请注明出处 -- polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比 ...

  7. 【原】FMDB源码阅读(一)

    [原]FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于 ...

  8. 【原】AFNetworking源码阅读(六)

    [原]AFNetworking源码阅读(六) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这一篇的想讲的,一个就是分析一下AFSecurityPolicy文件,看看AF ...

  9. 【原】AFNetworking源码阅读(五)

    [原]AFNetworking源码阅读(五) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中提及到了Multipart Request的构建方法- [AFHTTP ...

随机推荐

  1. scss、less 对浏览器兼容的处理方法, css 的单行溢出、多行溢出

    1. scss @mixin rounded($param1,$param2) {    #{$param1}:$param2;    -webkit-#{$param1}: $param2;     ...

  2. Vijos.lxhgww的奇思妙想(k级祖先 长链剖分)

    题目链接 https://blog.bill.moe/long-chain-subdivision-notes/ http://www.cnblogs.com/zzqsblog/p/6700133.h ...

  3. 潭州课堂25班:Ph201805201 爬虫基础 第十三课 cookie (课堂笔记)

    # -*- coding: utf-8 -*- # 斌彬电脑 # @Time : 2018/9/15 0015 4:52 #cookie 是服务器发给浏览器的特殊信息 # 可以理解为一个临时通行证 # ...

  4. 关于Gevent的使用指北

    关于Gevent的使用指北 只是看了入门指南,和一个翻译文档.写一下个人读书心得. 其实看完之后,第一个反映就是asyncio这个系统库,感觉gevent现在所做的一些事情是与asyncio很像的,但 ...

  5. 响应式 Web 设计指南「基础篇」

    Web 是普遍存在的,也是无处不在的,Web可以适应任何尺寸的屏幕以及任何使用环境,因为Web有其固有的灵活性和可塑性. Web 再也不是某一平台独有的矿藏,而是真正成为了一张名副其实的大网,并将各种 ...

  6. db2系统表相应功能

    SYSIBM: 基本系统编目,不建议直接访问SYSCAT: 默认授权给Public组.只读编目视图,一般通过这个来获取编目信息SYSSTAT: 可更新编目视图,会影响优化器的优化策略SYSFUN: 用 ...

  7. Asp.Net Mvc 自定义扩展

    目录: 自定义模型IModelBinder 自定义模型验证 自定义视图引擎 自定义Html辅助方法 自定义Razor辅助方法 自定义Ajax辅助方法 自定义控制器扩展 自定义过滤器 自定义Action ...

  8. iOS埋点统计

    链接: iOS无埋点数据SDK实践之路 iOS:无埋点数据SDK实践之路,看完能懂就厉害了 iOS埋点业务方案 ios 无码统计埋点 使用AOP实现iOS应用内的埋点计数 Aspects(AOP) A ...

  9. 中文分词组件:thulac及jieba试用手记

    一.THULAC THULAC由<清华大学自然语言处理与社会人文计算实验室>研制推出的一套中文词法分析工具包.官网地址:http://thulac.thunlp.org,该项目提供了多种语 ...

  10. 深入学习 FutureTask

    原文出处: 天凉好个秋 第一部分:What 在Java中一般通过继承Thread类或者实现Runnable接口这两种方式来创建多线程,但是这两种方式都有个缺陷,就是不能在执行完成后获取执行的结果,因此 ...