码迷,mamicode.com
首页 > 其他好文 > 详细

J.U.C Atomic(二)基本类型原子操作

时间:2018-01-04 22:46:17      阅读:216      评论:0      收藏:0      [点我收藏+]

标签:return   out   eof   ret   bubuko   field   cep   obj   命令   

java.util.concurrent.atomic包中对基本类型进行原子操作的类有:AtomicInteger、AtomicBoolean、AtomicLong。

下面通过一个测试程序来验证一下AtomicInteger真的实现了原子操作

 

public class AtomicIntegerTest {
    public static  AtomicInteger count=new AtomicInteger(0);
    public static void main(String[] args) throws IOException {
        /*一个线程递增10000次*/
        new Thread() {
            public void run() {
                for (int i = 0; i < 10000; i++) {

                    System.out.println(this.getName() + ">>" + count.addAndGet(1));
                }
            }

        }.start();
        /*
         * 两个线程分别递减5000次
         */
        new Thread() {
            public void run() {
                for (int i = 0; i < 5000; i++) {

                    System.out.println(this.getName() + ">>" + count.addAndGet(-1));
                }
            }

        }.start();

        new Thread() {
            public void run() {
                for (int i = 0; i < 5000; i++) {

                    System.out.println(this.getName() + ">>" + count.addAndGet(-1));
                }
            }

        }.start();
        System.in.read();
        System.out.println("最终结果:"+count);
    }
}

按照我们的预期如果最终结果是0,那么就可以说明确实实现了原子操作。

 技术分享图片

接下来我们通过源码看一下具体做了哪些操作:

public class AtomicInteger extends Number implements java.io.Serializable {
    private static final long serialVersionUID = 6214790243416807050L;

    // setup to use Unsafe.compareAndSwapInt for updates
    private static final Unsafe unsafe = Unsafe.getUnsafe();//Unsafe仅供JDK内部调用,我们写的程序不能直接调用
    private static final long valueOffset;//value在内存中的地址
  /*初始化value地址*/
    static {
      try {
        valueOffset = unsafe.objectFieldOffset
            (AtomicInteger.class.getDeclaredField("value"));
      } catch (Exception ex) { throw new Error(ex); }
    }

    private volatile int value;//用volatile修饰,value值被某个线程修改后其他线程可以读到最新值

通过查看源码发现update操作最终都是通过调用compareAndSet方法,也就是通过Unsafe调用C程序执行CPU命令。

/**
* Atomically sets to the given value and returns the old value.
*
* @param newValue the new value
* @return the previous value
*/
public final int getAndSet(int newValue) {
for (;;) {
int current = get();
if (compareAndSet(current, newValue))
return current;
}
}
/**
* Atomically increments by one the current value.
*
* @return the previous value
*/
public final int getAndIncrement() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return current;
}
}


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

另外,这种自旋的方式保证操作成功的方式在竞争激烈的情况对CPU资源消耗比较大。

因为基本类型的原子类都比较近简单,实现方式也比较接近,在这就不细说了。

AtomicBoolean 最终也是调用了unsafe.compareAndSwapInt方法,

AtomicLong最终调用了unsafe.compareAndSwapLong方法,AtomicLong会多一个判断虚拟机是否支持long型无锁CompareAndSet,不过好像也没用它做任何事,意义何在呢???

 /**
     * Records whether the underlying JVM supports lockless
     * compareAndSwap for longs. While the Unsafe.compareAndSwapLong
     * method works in either case, some constructions should be
     * handled at Java level to avoid locking user-visible locks.
     */
    static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();

    /**
     * Returns whether underlying JVM supports lockless CompareAndSet
     * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.
     */
    private static native boolean VMSupportsCS8();

 

J.U.C Atomic(二)基本类型原子操作

标签:return   out   eof   ret   bubuko   field   cep   obj   命令   

原文地址:https://www.cnblogs.com/monkey0307/p/8195175.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!