第十一章 AtomicInteger源码解析

1、原子类

  • 可以实现一些原子操作
  • 基于CAS

下面就以AtomicInteger为例。

2、AtomicInteger

在没有AtomicInteger之前,对于一个Integer的线程安全操作,是需要使用同步锁来实现的,当然现在也可以通过ReentrantLock来实现,但是最好最方便的实现方式是采用AtomicInteger。

具体示例:

package com.collection.test;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 原子类的测试
 */
public class AtomicTest {
    private static AtomicInteger atomicInteger = new AtomicInteger();

    //获取当前值
    public static void getCurrentValue(){
        System.out.println(atomicInteger.get());//-->0
    }

    //设置value值
    public static void setValue(){
        atomicInteger.set(12);//直接用12覆盖旧值
        System.out.println(atomicInteger.get());//-->12
    }

    //根据方法名称getAndSet就知道先get,则最后返回的就是旧值,如果get在后,就是返回新值
    public static void getAndSet(){
        System.out.println(atomicInteger.getAndSet(15));//-->12
    }

    public static void getAndIncrement(){
        System.out.println(atomicInteger.getAndIncrement());//-->15
    }

    public static void getAndDecrement(){
        System.out.println(atomicInteger.getAndDecrement());//-->16
    }

    public static void getAndAdd(){
        System.out.println(atomicInteger.getAndAdd(10));//-->15
    }

    public static void incrementAndGet(){
        System.out.println(atomicInteger.incrementAndGet());//-->26
    }

    public static void decrementAndGet(){
        System.out.println(atomicInteger.decrementAndGet());//-->25
    }

    public static void addAndGet(){
        System.out.println(atomicInteger.addAndGet(20));//-->45
    }

    public static void main(String[] args) {
        AtomicTest test = new AtomicTest();
        test.getCurrentValue();
        test.setValue();
        //返回旧值系列
        test.getAndSet();
        test.getAndIncrement();
        test.getAndDecrement();
        test.getAndAdd();
        //返回新值系列
        test.incrementAndGet();
        test.decrementAndGet();
        test.addAndGet();

    }
}

源代码:

    private volatile int value;// 初始化值

    /**
     * 创建一个AtomicInteger,初始值value为initialValue
     */
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }

    /**
     * 创建一个AtomicInteger,初始值value为0
     */
    public AtomicInteger() {
    }

    /**
     * 返回value
     */
    public final int get() {
        return value;
    }

    /**
     * 为value设值(基于value),而其他操作是基于旧值<--get()
     */
    public final void set(int newValue) {
        value = newValue;
    }

    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

    /**
     * 基于CAS为旧值设定新值,采用无限循环,直到设置成功为止
     *
     * @return 返回旧值
     */
    public final int getAndSet(int newValue) {
        for (;;) {
            int current = get();// 获取当前值(旧值)
            if (compareAndSet(current, newValue))// CAS新值替代旧值
                return current;// 返回旧值
        }
    }

    /**
     * 当前值+1,采用无限循环,直到+1成功为止
     * @return the previous value 返回旧值
     */
    public final int getAndIncrement() {
        for (;;) {
            int current = get();//获取当前值
            int next = current + 1;//当前值+1
            if (compareAndSet(current, next))//基于CAS赋值
                return current;
        }
    }

    /**
     * 当前值-1,采用无限循环,直到-1成功为止
     * @return the previous value 返回旧值
     */
    public final int getAndDecrement() {
        for (;;) {
            int current = get();
            int next = current - 1;
            if (compareAndSet(current, next))
                return current;
        }
    }

    /**
     * 当前值+delta,采用无限循环,直到+delta成功为止
     * @return the previous value  返回旧值
     */
    public final int getAndAdd(int delta) {
        for (;;) {
            int current = get();
            int next = current + delta;
            if (compareAndSet(current, next))
                return current;
        }
    }

    /**
     * 当前值+1, 采用无限循环,直到+1成功为止
     * @return the updated value 返回新值
     */
    public final int incrementAndGet() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return next;//返回新值
        }
    }

    /**
     * 当前值-1, 采用无限循环,直到-1成功为止
     * @return the updated value 返回新值
     */
    public final int decrementAndGet() {
        for (;;) {
            int current = get();
            int next = current - 1;
            if (compareAndSet(current, next))
                return next;//返回新值
        }
    }

    /**
     * 当前值+delta,采用无限循环,直到+delta成功为止
     * @return the updated value 返回新值
     */
    public final int addAndGet(int delta) {
        for (;;) {
            int current = get();
            int next = current + delta;
            if (compareAndSet(current, next))
                return next;//返回新值
        }
    }

    /**
     * 获取当前值
     */
    public int intValue() {
        return get();
    }

说明:使用与源代码都简单到爆了!自己看看注释。

注意:

  • value是volatile的,关于volatile的相关内容见《附2 volatile》,具体链接:http://www.cnblogs.com/java-zhao/p/5125698.html
  • 单步操作:例如set()是直接对value进行操作的,不需要CAS,因为单步操作就是原子操作。
  • 多步操作:例如getAndSet(int newValue)是两步操作-->先获取值,在设置值,所以需要原子化,这里采用CAS实现。
  • 对于方法是返回旧值还是新值,直接看方法是以get开头(返回旧值)还是get结尾(返回新值)就好
  • CAS:比较CPU内存上的值是不是当前值current,如果是就换成新值update,如果不是,说明获取值之后到设置值之前,该值已经被别人先一步设置过了,此时如果自己再设置值的话,需要在别人修改后的值的基础上去操作,否则就会覆盖别人的修改,所以这个时候会直接返回false,再进行无限循环,重新获取当前值,然后再基于CAS进行加减操作。
  • 如果还是不懂CAS,类比数据库的乐观锁
时间: 2024-12-30 02:48:02

第十一章 AtomicInteger源码解析的相关文章

第六章 ReentrantLock源码解析2--释放锁unlock()

最常用的方式: int a = 12; //注意:通常情况下,这个会设置成一个类变量,比如说Segement中的段锁与copyOnWriteArrayList中的全局锁 final ReentrantLock lock = new ReentrantLock(); lock.lock();//获取锁 try { a++;//业务逻辑 } catch (Exception e) { }finally{ lock.unlock();//释放锁 } 注:关于lock()方法的源码解析,请参照"第五章

第十四章 Executors源码解析

前边两章介绍了基础线程池ThreadPoolExecutor的使用方式.工作机理.参数详细介绍以及核心源码解析. 具体的介绍请参照: 第十二章 ThreadPoolExecutor使用与工作机理 第十三章 ThreadPoolExecutor源码解析 1.Executors与ThreadPoolExecutor ThreadPoolExecutor 可以灵活的自定义的创建线程池,可定制性很高 想创建好一个合适的线程池比较难 使用稍微麻烦一些 实际中很少使用 Executors 可以创建4种线程池

第四章 CopyOnWriteArraySet源码解析

注:在看这篇文章之前,如果对CopyOnWriteArrayList底层不清楚的话,建议先去看看CopyOnWriteArrayList源码解析. http://www.cnblogs.com/java-zhao/p/5121944.html 1.对于CopyOnWriteArraySet需要掌握以下几点 创建:CopyOnWriteArraySet() 添加元素:即add(E)方法 删除对象:即remove(E)方法 遍历所有对象:即iterator(),在实际中更常用的是增强型的for循环去

第六章 HashSet源码解析

6.1.对于HashSet需要掌握以下几点 HashSet的创建:HashSet() 往HashSet中添加单个对象:即add(E)方法 删除HashSet中的对象:即remove(Object key)方法 判断对象是否存在于HashSet中:containsKey(Object key)  注:HashSet没有获取单个对象的方法,需要使用iterator 6.2.构建HashSet 源代码: //HashSet底层数据结构:通过hashmap的key不可重复的原则,使得存放入HashSet

第三章 CopyOnWriteArrayList源码解析

注:在看这篇文章之前,如果对ArrayList底层不清楚的话,建议先去看看ArrayList源码解析. http://www.cnblogs.com/java-zhao/p/5102342.html 1.对于CopyOnWriteArrayList需要掌握以下几点 创建:CopyOnWriteArrayList() 添加元素:即add(E)方法 获取单个对象:即get(int)方法 删除对象:即remove(E)方法 遍历所有对象:即iterator(),在实际中更常用的是增强型的for循环去做

lesson8:AtomicInteger源码解析及性能分析

AtomicInteger等对象出现的目的主要是为了解决在多线程环境下变量计数的问题,例如常用的i++,i--操作,它们不是线程安全的,AtomicInteger引入后,就不必在进行i++和i--操作时,进行加锁操作,在我们日常工作中,有很多业务场景需要在多线程环境下进行变量的计数:订单数统计.访问量统计.累计相应时长统计等. demo 源码:https://github.com/mantuliu/javaAdvance 下面我们先分析一下AtomicInteger的源代码.通过源码分析我们知道

第二章 ArrayList源码解析

一.对于ArrayList需要掌握的七点内容 ArrayList的创建:即构造器 往ArrayList中添加对象:即add(E)方法 获取ArrayList中的单个对象:即get(int index)方法 删除ArrayList中的对象:即remove(E)方法 遍历ArrayList中的对象:即iterator,在实际中更常用的是增强型的for循环去做遍历 判断对象是否存在于ArrayList中:contain(E) ArrayList中对象的排序:主要取决于所采取的排序算法(以后讲) 二.源

第九章 LinkedBlockingQueue源码解析

1.对于LinkedBlockingQueue需要掌握以下几点 创建 入队(添加元素) 出队(删除元素) 2.创建 Node节点内部类与LinkedBlockingQueue的一些属性 static class Node<E> { E item;//节点封装的数据 /** * One of: * - the real successor Node * - this Node, meaning the successor is head.next * - null, meaning there

第五章 HashMap源码解析

以后再做记录 5.1.对于HashMap需要掌握以下几点 Map的创建:HashMap() 往Map中添加键值对:即put(Object key, Object value)方法 获取Map中的单个对象:即get(Object key)方法 删除Map中的对象:即remove(Object key)方法 判断对象是否存在于Map中:containsKey(Object key) 遍历Map中的对象:即keySet()和iterator,在实际中更常用的是增强型的for循环去做遍历 Map中对象的