`

atomic

 
阅读更多

 

Atomic 包中的类提供了对数据进行原子操作的功能。

例如
   a++ 、a+=1等类似代码不是原子的,实现过程是由内存中取出数据,对数据进行计算,再结果写入内存,属于复合操作,由多条CPU指令完成。   在单线程下这些代码会运行良好,如果a是多线程中的共享变量,那么运行结果可能会不正确。

举列: a表示一个累计值,以a++为例:

   X线程 从内存中取出a的值=5,执行a++,得出的结果是6,并未写回内存时前,Y线程从内存中取出a的值=5,X线程将a=6写回内存,但Y缓存中a的值=5,执行a++得出结果为6,写回内存a=6。 结果是两个线程分别对5进行加1操作,但结果等于6,累计值就少了1。 

  避免这种情况产生,可以采用如下方式:

    1.采用 synchronized或 ReentrainLock锁  ,某一时刻只能有一条线程对a操作,即线程互斥。(阻塞方式)

    2.采有原子类操作,将a定义为AtomicInteger或AtomicLong ,调用incrementAndGet方法加1. (非阻塞方式)

 

AtomicLong中的 incrementAndGet源码分析如下:

   private volatile long value;//long数据值 标记为 volatile 每次读取写入值在主内存中操作,而不是线程的缓存中,使值的变化其它线程立即可见。
   private static final Unsafe unsafe = Unsafe.getUnsafe(); //Unsafe 用于实现CAS(compare and swap) 操作,基于CPU一条原始指令,是原子的线程安全的,可用于多线程间非阻塞方式实现线程安全。
   static {
      try {
        valueOffset = unsafe.objectFieldOffset
            (AtomicLong.class.getDeclaredField("value"));//value值在内存中的偏移地址,用于直接修改内存值
      } catch (Exception ex) { throw new Error(ex); }
    }
    
      public final long getAndIncrement() {
        while (true) {//在循环中设定value的值,直至成功。
            long current = get();//取出主内存中的value值存入线程栈
            long next = current + 1;//线程栈中的value值+1
            if (compareAndSet(current, next))//原子的设定value值,如果返回值是假,说明当前主内存中的实际值与线程栈中的值不相等,可能其它线程修改了内存中值,需要基于新值再次计算,即又一次循环
                return current;
        }
    }
    
	/**
	*原子的操作方法,  
	* 如果expect(期望值)与value实际相等,说明数据没有被改过,就用update(新值)替换实际值并反回真,执行过程是原子的,线程安全,
	* 如果expect(期望值)与value实际相等,说明数据可能被改过,返回假。
	* 
	*/
  	public final boolean compareAndSet(long expect, long update) {
			return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
    }
    

 

 

 

  

 

java.util.concurrent.atomic 原子更新的包
包含:AtomicBoolean --原子的更新boolean值
      AtomicInteger --原子的更新integer值
      AtomicLong   --原子的更新long值

      AtomicLongArray --原子的更新long数组
      AtomicIntegerArray --原子的更新int数组

      AtomicReference  --原子的更新一个对象引用
      AtomicReferenceFieldUpdater --原子的更新一个类实例中属性的引用
      AtomicIntegerFieldUpdater --原子的更新一个类实例中int属性值
      AtomicLongFieldUpdater  --原子的更新一个类实例中long属性值

      这些类基于unsafe类,使用cas方法和 volatile 来保证原子操作:
         1,Unsafe类提供了硬件级别的原子操作,cas(compare and swap) 基于比较交换的方式(当前值相等的情况下,再设置新值),使用的方式
         2. volatile 保证了内存的可见性。


    /**
     *
     *  当前值+1,并返回当前值,原子的
     *
     */
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }

   /**
   *   通过cas方式,不断循环设置新值,直到成功,返回旧值。
   *
   */
    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;
    }



 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics