AtomicInteger

2019-02-24  本文已影响17人  云师兄

1. 引子

在之前《CountDownLatch和Semaphore》一章最后的例子留下了一个问题,即多线程并发访问时出现不一致的线程不安全问题,为此本节将对其进行修改以满足线程安全的要求,并引入atomic包中的AtomicInteger类的相关介绍。

2. 使用AtomicInteger确保一致性

对示例代码修改如下:

public class ConcurrencyTest {

    // 请求总数
    public static int clientTotal = 5000;

    // 同时并发执行的线程数
    public static int threadTotal = 200;

    // public static int count = 0; // 存在线程安全问题
    public static AtomicInteger count = new AtomicInteger(0);

    public static void main(String[] args) throws InterruptedException {

        // 创建线程池
        ExecutorService executorService = Executors.newCachedThreadPool();

        // 信号量
        final Semaphore semaphore = new Semaphore(threadTotal);

        // 计数器闭锁
        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);

        for (int i=0;i<clientTotal;i++){
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        semaphore.acquire();
                        add();
                        semaphore.release();
                    } catch (Exception e){
                        System.out.println(e);
                    }
                    // 每个线程执行时计数器都减1
                    countDownLatch.countDown();
                }
            });
        }

        System.out.println("countDownLatch is awaiting!");
        countDownLatch.await();

        executorService.shutdown();
        System.out.println("count="+count.get());
    }

    public static void add(){
        //count ++;
        count.getAndIncrement();
    }
}

从上述示例可知,我们修改了如下内容:

3. AtomicInteger源码分析

要想理解其实现原理,主要分析下count.getAndIncrement();方法实现,源码如下:

    private static final Unsafe unsafe = Unsafe.getUnsafe();
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }

实现主要调用了Unsafe类的getAndAddInt()方法,传入第一个参数为当前对象count,第一个参数为当前对象的值,比如当前循环中count值为2,第三个参数为每次递增1。进入这个方法:

   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;
    }
    public native int getIntVolatile(Object var1, long var2);
    public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

getAndAddInt()方法中涉及到的两个方法调用如上都定义为native,即java底层实现的本地方法(JNI),这里就不深入查看实现了,主要说下做了什么:

上一篇 下一篇

猜你喜欢

热点阅读