前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >AtomicInteger原子类原理解析

AtomicInteger原子类原理解析

作者头像
黑洞代码
发布2021-01-14 15:16:09
3100
发布2021-01-14 15:16:09
举报

本节主要讲解Atomic打头的原子类的使用和原理。

关联博客

原子操作

原子操作是指不会被线程调度机制打断的操作,这种操作一旦开始,就一直运行到结束,中间不会有任何线程上下文切换。

原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序不可以被打乱,也不可以被切割而只执行其中的一部分,将整个操作视作一个整体是原子性的核心特征。

原子类

在java中提供了很多原子类,主要把这些原子类分成四大类。

原子更新基本类型或引用类型

  1. AtomicBoolean

原子更新布尔类型,内部使用int类型的value存储1和0表示true和false,底层也是对int类型的原子操作。

  1. AtomicInteger

原子更新int类型。

  1. AtomicLong

原子更新long类型。

  1. AtomicReference

原子更新引用类型,通过泛型指定要操作的类。

  1. AtomicMarkableReference

原子更新引用类型,内部使用Pair承载引用对象及是否被更新过的标记,避免了ABA问题。

  1. AtomicStampedReference

原子更新引用类型,内部使用Pair承载引用对象及更新的邮戳,避免了ABA问题。

原子更新数组中的元素

原子更新数组中的元素,可以更新数组中指定索引位置的元素,这些类主要有:

  1. AtomicIntegerArray

原子更新int数组中的元素。

  1. AtomicLongArray

原子更新long数组中的元素。

  1. AtomicReferenceArray

原子更新Object数组中的元素。

原子更新对象中的字段

原子更新对象中的字段,可以更新对象中指定字段名称的字段,这些类主要有:

  1. AtomicIntegerFieldUpdater

原子更新对象中的int类型字段。

  1. AtomicLongFieldUpdater

原子更新对象中的long类型字段。

  1. AtomicReferenceFieldUpdater

原子更新对象中的引用类型字段。

高性能原子类

高性能原子类,是java8中增加的原子类,它们使用分段的思想,把不同的线程hash到不同的段上去更新,最后再把这些段的值相加得到最终的值,这些类主要有:

  1. Striped64

下面四个类的父类。

  1. LongAccumulator

long类型的聚合器,需要传入一个long类型的二元操作,可以用来计算各种聚合操作,包括加乘等。

  1. LongAdder

long类型的累加器,LongAccumulator的特例,只能用来计算加法,且从0开始计算。

  1. DoubleAccumulator

double类型的聚合器,需要传入一个double类型的二元操作,可以用来计算各种聚合操作,包括加乘等。

  1. DoubleAdder

double类型的累加器,DoubleAccumulator的特例,只能用来计算加法,且从0开始计算。

AtomicInteger使用

代码语言:javascript
复制
package com.example.atomic.atomicinteger.demo;
import	java.util.concurrent.atomic.AtomicInteger;


/**
 * @Author: 无双老师【云析学院:http://yunxiedu.net QQ:3190976240 email:zhouguanya20@163.com】
 * @Date: 2020-03-21 16:20
 * @Description: AtomicInteger使用方式
 */
public class AtomicIntegerDemo {

    public static void main(String[] args) throws InterruptedException {
        test1();
        test2();
    }

    private static void test1() throws InterruptedException {
        Counter counter = new Counter();
        // 100个线程
        for (int i = 0; i < 10; i++) {
            // 每个线程对count累加10次
            new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    counter.addCount();
                }
            }).start();
        }
        Thread.sleep(1000);
        System.out.println("count = " + counter.getCount());
    }

    private static void test2() throws InterruptedException {
        /**
         * 原子性的int
         */
        AtomicInteger count = new AtomicInteger();
        // 100个线程
        for (int i = 0; i < 10; i++) {
            // 每个线程对count累加10次
            new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    count.incrementAndGet();
                }
            }).start();
        }
        Thread.sleep(1000);
        System.out.println("count = " + count.get());
    }
}


/**
 * volatile修饰的计数器
 */
private volatile static int count = 0;

public void addCount() {
	count++;
}

public int getCount() {
	 return count;
}

AtomicInteger原理

AtomicInteger声明

代码语言:javascript
复制
public class AtomicInteger extends Number implements java.io.Serializable

Unsafe类的使用

代码语言:javascript
复制
// setup to use Unsafe.compareAndSwapInt for updates
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); }
}

AtomicInteger属性

代码语言:javascript
复制
 private volatile int value;

AtomicInteger构造器

代码语言:javascript
复制
    /**
     * Creates a new AtomicInteger with the given initial value.
     *
     * @param initialValue the initial value
     */
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }

    /**
     * Creates a new AtomicInteger with initial value {@code 0}.
     */
    public AtomicInteger() {
    }

AtomicInteger自增

代码语言:javascript
复制
    /**
     * Atomically increments by one the current value.
     *
     * @return the updated value
     */
    public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }
	

调用Unsafe类的方法如下。

代码语言:javascript
复制
    public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

        return var5;
    }

注意观察compareAndSwapInt即CAS方式修改int值。

AtomicInteger.incrementAndGet方法自增的原理:

  1. 调用unsafe.getAndAddInt方法
  2. unsafe.getAndAddInt方法通过自旋的方式,每次尝试通过CAS方法对原值进行累加。如果累加失败,将进入下一次循环。如果累加成功,则自旋结束。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 落叶飞翔的蜗牛 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 关联博客
  • 原子操作
  • 原子类
    • 原子更新基本类型或引用类型
      • 原子更新数组中的元素
        • 原子更新对象中的字段
          • 高性能原子类
          • AtomicInteger使用
          • AtomicInteger原理
            • AtomicInteger声明
              • Unsafe类的使用
                • AtomicInteger属性
                  • AtomicInteger构造器
                    • AtomicInteger自增
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档