Java并发编程之美 chap4 原子性操作类源码剖析笔记

本文主要剖析Java并发编程中的AtomicLong类,详细解释了其原子性递增、递减操作的实现,以及CompareAndSet方法的工作原理。通过实例展示了AtomicLong如何确保在多线程环境下操作的原子性,保证数据一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

4-1 原子变量操作类

这种类的作用其实就是

在线程之中调用这个类,向它的构造函数传递一个value(注意,这个value是一个Long类型的值) 然后用这个类的方法对这个值进行原子性的递增递减操作。

以AtomicLong类来详细分析源码

(好像书中用的版本的代码和我现在使用的又不一样了,我现在用书中的代码)

构造函数为:

  public AtomicLong(long initialValue) {
        this.value = initialValue;
    }

    public AtomicLong() {
    }

以下是AtomicLong类中用到的内部变量以及它们的用处

public class AtomicLong extends Number implements Serializable {
    private static final long serialVersionUID = 1927816293512124184L;
    
    //实际要操作的值value
    private volatile long value;
    //获取Unsafe实例
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    //存放value的偏移量
    private static final long VALUE;
    

    //判断JVM是不是支持Long类型无锁CAS(不懂)
    static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
    private static native boolean VMSupportsCS8();
    
     static {
        try{
            //获取value的偏移量
            VALUE = unsafe.objectFieldOffset(AtomicLong.class, "value");
        }catch(Exception ex){throw new Error(ex);}
    }

    //构造函数
    public AtomicLong(long initialValue) {
        this.value = initialValue;
    }
    
    public AtomicLong() {
    }

1.递增和递减操作代码

最关键的是类中的原子性操作的实现(它们的作用是对value实行原子性的操作)

它们都大同小异:

public final long getAndIncrement() {
        return unsafe.getAndAddLong(this, VALUE, 1L);
    }
public final long incrementAndGet() {
        return unsafe.getAndAddLong(this, VALUE, 1L) + 1L;
    }
public final long decrementAndGet() {
        return unsafe.getAndAddLong(this, VALUE, -1L) - 1L;
    }

它们都是调用unsafe的getAndAddLong,这个函数是个原子性操作,这里第一个参数是 AtomicLong 实例的引用 第二个参数是 value 变量AtomicLong 中的偏移值,第三个参数是要设置的第二个变量的值。

Unsafe中的getAndAddLong代码为:

public final long getAndAddLong(Object o, long offset, long delta) {
        long v;
        do {
            v = this.getLongVolatile(o, offset);
        } while(!this.weakCompareAndSetLong(o, offset, v, v + delta));

        return v;
    }

解释:这个方法被上面的方法调用,结合起来的意识就是拿到value的当前值,然后在工作内存中对其进行+1操作。

2. boolean CompareAndSet方法

这是AtomicLong中一系列方法

public final boolean CompareAndSet(long expect, long update) {
        return unsafe.compareAndSwapLong(this, VALUE, expect, update);
    }

它还是调用的是Unsafe中的compareAndSwapLong方法:如果原子变量中的value等于expect,则用update更新之,并返回true。否则返回false。

3.例子

加深理解

import java.util.concurrent.atomic.AtomicLong;

public class AtomicTest {

    //AtomicLong数组
    private static AtomicLong atomicLong=new AtomicLong();
    //数据源头
    private static Integer[] arrayone=new Integer[]{0,1,2,3,0,5,6,0,56,0};
    private static Integer[] arraytwo=new Integer[]{10,1,2,3,0,5,6,0,56,0};

    public static void main(String[] args) throws InterruptedException {
        //线程1统计arrayone数组中0的个数
        Thread threadone=new Thread(new Runnable() {
            @Override
            public void run() {
                int size=arrayone.length;
                for(int i=0;i<size;i++)
                {
                    if(arrayone[i]==0)
                        atomicLong.incrementAndGet();
                }
            }
        });

        Thread threadtwo=new Thread(new Runnable() {
            @Override
            public void run() {
                int size=arraytwo.length;
                for(int i=0;i<size;i++)
                {
                    if(arraytwo[i]==0)
                        atomicLong.incrementAndGet();
                }
            }
        });

        //启动子线程
        threadone.start();
        threadtwo.start();

        //等待线程执行完毕
        threadone.join();
        threadtwo.join();

        System.out.println("count 0:"+atomicLong.get());

    }
}

输出为:

在这里插入图片描述

这代表两个线程利用的atomic对象进行的操作是原子性的,没有发生混乱

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值