美文网首页
Java多线程系列--(JUC原子类)

Java多线程系列--(JUC原子类)

作者: 小飞剑客 | 来源:发表于2020-05-28 17:07 被阅读0次

欢迎来到飞之折翼的简书,待双翼饱满就是飞翔之际!


源自摘要:https://www.cnblogs.com/skywang12345/p/java_threads_category.html

一、框架

根据修改的数据类型,可以将JUC包中的原子操作类可以分为4类。

1.基本类型: AtomicInteger, AtomicLong, AtomicBoolean ;

2.数组类型: AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray ;

3.引用类型: AtomicReference, AtomicStampedRerence, AtomicMarkableReference ;

4.对象的属性修改类型: AtomicIntegerFieldUpdater, AtomicLongFieldUpdater, AtomicReferenceFieldUpdater 。

这些类存在的目的是对相应的数据进行原子操作。所谓原子操作,是指操作过程不会被中断,保证数据操作是以原子方式进行的。

二、AtomicLong原子类

AtomicLong是作用是对长整形进行原子操作。

在32位操作系统中,64位的long 和 double 变量由于会被JVM当作两个分离的32位来进行操作,所以不具有原子性。而使用AtomicLong能让long的操作保持原子型

AtomicLong的代码很简单,下面仅以incrementAndGet()为例,对AtomicLong的原理进行说明。

incrementAndGet()源码如下

publicfinallong incrementAndGet() {

    for (;;) {

        // 获取AtomicLong当前对应的long值

        longcurrent = get();

        // 将current加1

        longnext = current + 1;

        // 通过CAS函数,更新current的值

        if (compareAndSet(current, next))

              return next;

        }

}

(01) incrementAndGet()首先会根据get()获取AtomicLong对应的long值。该值是volatile类型的变量,get()的源码如下:

// value是AtomicLong对应的long值

privatevolatilelong value;

// 返回AtomicLong对应的long值

publicfinallong get() {

    return value;

}

(02) incrementAndGet()接着将current加1,然后通过CAS函数,将新的值赋值给value。

compareAndSet()的源码如下:

publicfinalbooleancompareAndSet(longexpect,long update) {

    returnunsafe.compareAndSwapLong(this, valueOffset, expect, update);

}

compareAndSet()的作用是更新AtomicLong对应的long值。它会比较AtomicLong的原始值是否与expect相等,若相等的话,则设置AtomicLong的值为update。

三、AtomicLongArray原子类

AtomicLongArray的代码很简单,下面仅以incrementAndGet()为例,对AtomicLong的原理进行说明。

incrementAndGet()源码如下:

publicfinallongincrementAndGet(int i) {

    returnaddAndGet(i, 1);

}

说明:incrementAndGet()的作用是以原子方式将long数组的索引 i 的元素加1,并返回加1之后的值。

addAndGet()源码如下:

publiclongaddAndGet(inti,long delta) {

    // 检查数组是否越界

    longoffset = checkedByteOffset(i);

    while(true) {

        // 获取long型数组的索引 offset 的原始值

        longcurrent = getRaw(offset);

        // 修改long型值

        longnext = current + delta;

        // 通过CAS更新long型数组的索引 offset的值。

        if (compareAndSetRaw(offset, current, next))

            return next;

        }

}

说明:addAndGet()首先检查数组是否越界。如果没有越界的话,则先获取数组索引i的值;然后通过CAS函数更新i的值

private boolean compareAndSetRaw(longoffset,longexpect,long update) {

    return unsafe.compareAndSwapLong(array, offset, expect, update);

}

四、AtomicReference原子类

AtomicReference的源码比较简单。它是通过"volatile"和"Unsafe提供的CAS函数实现"原子操作。

(01) value是volatile类型。这保证了:当某线程修改value的值时,其他线程看到的value值都是最新的value值,即修改之后的volatile的值。

(02) 通过CAS设置value。这保证了:当某线程池通过CAS函数(如compareAndSet函数)设置value时,它的操作是原子的,即线程在操作value时不会被中断。

AtomicReference示例

// AtomicReferenceTest.java的源码import java.util.concurrent.atomic.AtomicReference;publicclass AtomicReferenceTest {

    publicstaticvoid main(String[] args){

        // 创建两个Person对象,它们的id分别是101和102。

        Person p1 =newPerson(101);

        Person p2 =newPerson(102);

        // 新建AtomicReference对象,初始化它的值为p1对象

        AtomicReference ar =new AtomicReference(p1);

        // 通过CAS设置ar。如果ar的值为p1的话,则将其设置为p2。

        ar.compareAndSet(p1, p2);    

        Person p3 = (Person)ar.get();

        System.out.println("p3 is "+p3);

        System.out.println("p3.equals(p1)="+p3.equals(p1));

    }

    }class Person {

    volatilelong id;

    publicPerson(long id) {

        this.id = id;

    }

    public String toString() {

        return"id:"+id;

    }

}

五、AtomicLongFieldUpdater原子类

// LongTest.java的源码

import java.util.concurrent.atomic.AtomicLongFieldUpdater;

public class LongFieldTest {

    public static void main(String[] args) {

        // 获取Person的class对象

        Class cls = Person.class;

        // 新建AtomicLongFieldUpdater对象,传递参数是“class对象”和“long类型在类中对应的名称”

        AtomicLongFieldUpdater mAtoLong = AtomicLongFieldUpdater.newUpdater(cls, "id");

        Person person = new Person(12345678L);

        // 比较person的"id"属性,如果id的值为12345678L,则设置为1000。

        mAtoLong.compareAndSet(person, 12345678L, 1000);

        System.out.println("id="+person.getId());

    }

}

class Person {

    volatile long id;

    public Person(long id) {

        this.id = id;

    }

    public void setId(long id) {

        this.id = id;

    }

    public long getId() {

        return id;

    }

}

newUpdater()的作用是获取一个AtomicIntegerFieldUpdater类型的对象。

它实际上返回的是CASUpdater对象,或者LockedUpdater对象;具体返回哪一个类取决于JVM是否支持long类型的CAS函数。CASUpdater和LockedUpdater都是AtomicIntegerFieldUpdater的子类,它们的实现类似。

它实际上是通过CAS函数操作。如果类的long对象的值是expect,则设置它的值为update。

相关文章

网友评论

      本文标题:Java多线程系列--(JUC原子类)

      本文链接:https://www.haomeiwen.com/subject/pqneahtx.html