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. ReportNG报表显示中文乱码和TestNG显示中文乱码实力解决办法

    最近在进军测试自动化框架学习阶段,但无意间总是会伴随小问题的困扰,比如中文乱码,而导致显示总是不舒服,个人觉得,就一定要解决,似乎有点点强迫症.所以遇到ReportNG报表显示中文乱码和TestNG显 ...

  2. Linux成长之路

    Linux命令格式: 命令   选项 参数command [-options] [parameter1] ···· 常用命令: tree 以目录树的方式显示: tree / 以目录树方式显示根目录结构 ...

  3. C#全能数据库操作类及调用示例

    C#全能数据库操作类及调用示例 using System; using System.Data; using System.Data.Common; using System.Configuratio ...

  4. 潭州课堂25班:Ph201805201 爬虫基础 第十四课 js破解 (课堂笔记)

    打断点 找要的数据 鼠标的点击事件 新浪微博登录 表单提交分析 : 先佃输入错误密码开始调式 f10 往下走, f11 进入函数 sh + f11 跳出函数 # -*- coding: utf-8 - ...

  5. PCB编译时出现的错误 ( Duplicate Net Names Wire N000-1 (Inferred)意思就是端口名字没有定义)

    再运行这个错误Duplicate Net Names Wire N000-1 (Inferred)的就没有了, 不过还有其他的 错误,有错误不用怕,关我的博客解决.

  6. su 与 su - 比较

    原文地址:http://blog.chinaunix.net/uid-25557346-id-2889329.html   今天有一同事说在切换用户的时候,找不到该用户下用户命令,后来仔细检查了一下过 ...

  7. scrollView 刷新显示在中间的问题

    scrollView问题 打开activity之后 屏幕初始位置不是顶部 而是在中间 也就是scroll滚动条不在上面 而是在中间 楼主你好,我大概是和你遇见了同样的问题,你可以灵活处理一下,不要去管 ...

  8. JVM Debugger Memory View for IntelliJ IDEA

    Posted on August 19, 2016 by Andrey Cheptsov Every day we try to find new ways to improve developer ...

  9. MUI右滑关闭窗口用Webview的drag实现

    mui.init({swipeBack:true}); 必须要用很快的速度摩擦屏幕才能达到右滑关闭窗口的效果,且在右边一般都会失效. mui这个滑动,是纯前端的,这个效率在Android上确实一般. ...

  10. python unknown error: DevToolsActivePort file doesn't exist 问题解决

    解决方案: from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_option ...