`
wsmajunfeng
  • 浏览: 491404 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Java Atomic

 
阅读更多

我们知道volatile修饰的变量可以实现基本的加载和赋值的原子性,但是对于像i++等操作就不能保证原子性了,在JDK1.5之前我们只能通过 synchronized(阻塞的方式)实现这些复合操作的原子性,在JDK1.5中java.util.concurrent.atomic 包提供了若干个类能实现对int,long,boolean,reference的几个特殊方法非阻塞原子性,这一系列类的主要基于以下两点

1.volatile修饰变量,保证get()/set()的原子性
2.利用系统底层的CAS原语来实现非阻塞的其它方法原子操作
  compareAndSwap(memorylocation,expectedValue,newValue);该操作接受一个预计值和新的赋值,当预计值与实际值相符合时,就表明该变量在此期间没有被别的线程改变(可能有ABA问题),就把新值赋给该引用.
  通常将 CAS 用于同步的方式是从地址 V 读取值 A,执行多步计算来获得新值 B,然后使用 CAS 将 V 的值从 A 改为 B。如果 V 处的值尚未同时更改,则 CAS 操作成功


各个类的介绍

1.AtomicInteger
  实现了对Int的各种操作的原子化,我们看看其中的方法
   
   //实现atomic类的最大诀窍#####
    public final boolean compareAndSet(int expect, int update) {
        //如果内存位置的值与期望值相同则,赋予新值,并返回true
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

   //该方法实现了i++的非阻塞的原子操作
   public final int getAndIncrement() {
        for (;;) { //循环,使用CAS的经典方式,这是实现non-blocking方式的代价
            int current = get();//得到现在的值
            int next = current + 1;//通过计算得到要赋予的新值
            if (compareAndSet(current, next)) //关键点,调用CAS原子更新,
                return current;
        }
    }

  

2.AtmoicLong
  与AtomicInteger相似,只是是基于Long

3.AtmoicBoolean
  与AtomimcInteger相似,基于boolean
4.AtomicReference
  与上述三个类不同,该类是用于原子地更新某个引用,只提供操作保证某个引用的更新会被原子化,常用封装某个引用会被多个线程频繁更新的场景,保证线程安全性

public final V getAndSet(V newValue) {
        while (true) {
            V x = get();
            if (compareAndSet(x, newValue))
                return x;
        }
    }


======================================================================

5.AtomicIntegerArray
  对数组中的制定int提供几种特定的原子操作,注意不是对这个数组对象进行原子操作
    //对数组的第i个元素进行原子的i--操作
    //注意该类的原子操作都是针对数组中的某个指定元素的
     public final int getAndDecrement(int i) {
        while (true) {
            int current = get(i);
            int next = current - 1;
            if (compareAndSet(i, current, next))
                return current;
        }
    }

6.AtomicLongArray
  与AtomicIntegerArray相似,基于long的
7.AtomicReferenceArray
  与AtomicIntegerArray相似,基于reference的
======================================================================
8.AtomicLongFieldUpdater
  上述的7个类都是基于对类自身的volatile数据提供原子操作,但是如何对已经存在的类中的volatile数据提供原子支持呢,这个需求是很常见 的,因为我们在日常开发中经常要使用第三方的class.8#9#10这三个类就是利用反射机制对指定类的指定的volatile field提供原子操作的工具类.这三个类在原子数据结构中被用到,可以参考源码.注意只对public volatile的非static 成员起作用
//工厂方法,给指定类的指定fild(必须是long)建立一个update,field必须是volatile的
public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName)

9.AtomicIntegerFieldUpdater
与上述类相似,只是基于int
10.AtomicReferenceFieldUpdater
  基于Reference
======================================================================
11.AtomicMarkableReference
12.AtomicStampedReference

 

 

 

 

 

 

 

 

 

J2SE 5.0提供了一组atomic class来帮助我们简化同步处理。基本工作原理是使用了同步synchronized的方法实现了对一个long, integer, 对象的增、减、赋值(更新)操作. 比如对于++运算符AtomicInteger可以将它持有的integer 能够atomic 地递增。在需要访问两个或两个以上 atomic变量的程序代码(或者是对单一的atomic变量执行两个或两个以上的操作)通常都需要被synchronize以便两者的操作能够被当作是 一个atomic的单元。

对array atomic变量来说,一次只有一个索引变量可以变动,并没有功能可以对整个array做atomic化的变动。

关于Atomic的几个方法
getAndSet() : 设置新值,返回旧值.
compareAndSet(expectedValue, newValue) : 如果当前值(current value)等于期待的值(expectedValue), 则原子地更新指定值为新值(newValue), 如果更新成功,返回true, 否则返回false, 换句话可以这样说: 将原子变量设置为新的值, 但是如果从我上次看到的这个变量之后到现在被其他线程修改了(和我期望看到的值不符), 那么更新失败

从effective java (2)中拿来的一个关于AtomicReference的一个例子:
Java代码

Java代码 复制代码  收藏代码
  1. public   class  AtomicTest {      
  2.      private   int  x, y;      
  3.      
  4.      private   enum  State {      
  5.         NEW, INITIALIZING, INITIALIZED      
  6.     };      
  7.      
  8.      private   final  AtomicReference<State> init =  new  AtomicReference<State>(State.NEW);      
  9.           
  10.      public  AtomicTest() {      
  11.     }      
  12.           
  13.      public  AtomicTest( int  x,  int  y) {      
  14.         initialize(x, y);      
  15.     }      
  16.      
  17.      private   void  initialize( int  x,  int  y) {      
  18.          if  (!init.compareAndSet(State.NEW, State.INITIALIZING)) {      
  19.              throw   new  IllegalStateException( "initialize is error" );      
  20.         }      
  21.          this .x = x;      
  22.          this .y = y;      
  23.         init.set(State.INITIALIZED);      
  24.     }      
  25.      
  26.      public   int  getX() {      
  27.         checkInit();      
  28.          return  x;      
  29.     }      
  30.      
  31.      public   int  getY() {      
  32.         checkInit();      
  33.          return  y;      
  34.     }      
  35.           
  36.      private   void  checkInit() {      
  37.          if  (init.get() == State.INITIALIZED) {      
  38.              throw   new  IllegalStateException( "uninitialized" );      
  39.         }      
  40.     }      
  41.           
  42. }   

上面的例子比较容易懂, 不过貌似没什么价值, 而在实际的应用中, 我们一般采用下面的方式来使用atomic class:
Java代码

Java代码 复制代码  收藏代码
  1. public   class  CounterTest {      
  2.     AtomicInteger counter =  new  AtomicInteger( 0 );      
  3.      
  4.      public   int  count() {      
  5.          int  result;      
  6.          boolean  flag;      
  7.          do  {      
  8.             result = counter.get();      
  9.              // 断点      
  10.              // 单线程下, compareAndSet返回永远为true,      
  11.              // 多线程下, 在与result进行compare时, counter可能被其他线程set了新值, 这时需要重新再取一遍再比较,      
  12.              // 如果还是没有拿到最新的值, 则一直循环下去, 直到拿到最新的那个值      
  13.             flag = counter.compareAndSet(result, result +  1 );      
  14.         }  while  (!flag);      
  15.      
  16.          return  result;      
  17.     }      
  18.      
  19.      public   static   void  main(String[] args) {      
  20.          final  CounterTest c =  new  CounterTest();      
  21.          new  Thread() {      
  22.              @Override      
  23.              public   void  run() {      
  24.                 c.count();      
  25.             }      
  26.         }.start();      
  27.      
  28.          new  Thread() {      
  29.              @Override      
  30.              public   void  run() {      
  31.                 c.count();      
  32.             }      
  33.         }.start();      
  34.      
  35.          new  Thread() {      
  36.              @Override      
  37.              public   void  run() {      
  38.                 c.count();      
  39.             }      
  40.         }.start();      
  41.     }      

类似i++这样的"读-改-写"复合操作(在一个操作序列中, 后一个操作依赖前一次操作的结果), 在多线程并发处理的时候会出现问题, 因为可能一个线程修改了变量, 而另一个线程没有察觉到这样变化, 当使用原子变量之后, 则将一系列的复合操作合并为一个原子操作,从而避免这种问题, i++=>i.incrementAndGet()
原子变量只能保证对一个变量的操作是原子的, 如果有多个原子变量之间存在依赖的复合操作, 也不可能是安全的, 另外一种情况是要将更多的复合操作作为一个原子操作, 则需要使用synchronized将要作为原子操作的语句包围起来. 因为涉及到可变的共享变量(类实例成员变量)才会涉及到同步, 否则不必使用synchronized

 

 

 

 

分享到:
评论
1 楼 lyp2002924 2015-08-19  
讲的,看到的最清晰明白的。

相关推荐

    Java Atomic类及线程同步新机制原理解析

    主要介绍了Java Atomic类及线程同步新机制原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    深入了解Java atomic原子类的使用方法和原理

    主要介绍了深入了解Java atomic原子类的使用方法和原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,,需要的朋友可以参考下

    Java多线程atomic包介绍及使用方法

    主要介绍了Java多线程atomic包介绍及使用方法,涉及原子更新基本类型介绍及代码示例,具有一定参考价值,需要的朋友可以了解下。

    浅谈Java中的atomic包实现原理及应用

    主要介绍了浅谈Java中的atomic包实现原理及应用,涉及Atomic在硬件上的支持,Atomic包简介及源码分析等相关内容,具有一定借鉴价值,需要的朋友可以参考下。

    atomic-mock-free-tier:模拟用户功能以匹配免费原子层上的用户功能

    无原子模拟层 嘲笑用户功能以匹配免费原子层上的功能,该功能在map_atomic_plan_cap中的map_atomic_plan_cap中定义

    java线程-Atomic的含义及示例_.docx

    java线程-Atomic的含义及示例_.docx

    JAVA_API1.6文档(中文)

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...

    Java多线程Atomic包操作原子变量与原子类详解

    主要介绍了Java多线程Atomic包操作原子变量与原子类详解,简单介绍了Atomic,同时涉及java.util.concurrent中的原子变量,Atomic类的作用等相关内容,具有一定参考价值,需要的朋友可以了解下。

    Java并发编程包中atomic的实现原理示例详解

    主要给大家介绍了关于Java并发编程包中atomic的实现原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    Java 1.6 API 中文 New

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 JAR ...

    JavaAPI1.6中文chm文档 part1

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...

    java api最新7.0

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 JAR ...

    Java Language Features 2nd Edition

    The chapter on threads follows this up and discusses everything from the very basic concepts of a thread to the most advanced topics such as synchronizers, the fork/join framework, and atomic ...

    ZooKeeper’s atomic broadcast protocol 翻译版

    ZooKeeper’s atomic broadcast protocol 翻译版

    Sparklingredstar#JavaBooks#Java多线程-Atomic原子类1

    引言JavaGuide :一份涵盖大部分Java程序员所需要掌握的核心知识。star:45159,替他宣传一下子这位大佬,总结的真好!我引用这位大佬的文章,因为

    atomic-array-rs:定义几种数组类型,其中元素可以原子更新。 旨在提供类似于Java中的java.util.concurrent.atomic中的原子数组类型

    旨在提供类似于Java中的java.util.concurrent.atomic中的原子数组类型。 提供以下类型: AtomicOptionRefArray –对应于 。 AtomicRefArray –具有强制默认值的AtomicOptionRefArray ,用于删除元素的可选属性。...

    JAVA面试必成功之JAVA面试秘籍

    JAVA面试秘籍一份通向理想互联网公司的面试汇总,包括Java基础、Java并发、JVM、MySQL、...七、Atomic 原子类 八、MySQL 九、Redis 十、Spring 十一、MyBatis 十二、MQ 十三、计算机网络 十四、操作系统 十五、Dubbo

    java jdk-api-1.6 中文 chmd

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...

    JavaAPI中文chm文档 part2

    java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 ...

Global site tag (gtag.js) - Google Analytics