java基础——AtomicInteger的并发处理

来源:互联网 发布:python简明教程pdf下载 编辑:程序博客网 时间:2024/05/21 04:19

转自http://my.oschina.net/u/1034537/blog/523747

jdk5之后的java.util.concurrent.atomic包里,多了一批原子处理类。主要用于在高并发环境下的高效程序处理。

这里,我们来看看AtomicInteger是如何使用非阻塞算法来实现并发控制的。


AtomicInteger的关键域只有一下3个:

 // setup to use Unsafe.compareAndSwapInt for updates  private static final Unsafe unsafe = Unsafe.getUnsafe();  private static final long valueOffset;  private volatile int value;

 这里, unsafe是java提供的获得对对象内存地址访问的类,注释已经清楚的写出了,它的作用就是在更新操作时提供“比较并替换”的作用。实际上就是AtomicInteger中的一个工具。


valueOffset是用来记录value本身在内存的便宜地址的,这个记录,也主要是为了在更新操作在内存中找到value的位置,方便比较

注意:value是用来存储整数的时间变量,这里被声明为volatile,就是为了保证在更新操作时,当前线程可以拿到value最新的值(并发环境下,value可能已经被其他线程更新了)。

这里,我们以自增的代码为例,可以看到这个并发控制的核心算法:

J2SE 5.0提供了一组atomic class来处理更加复杂的情况。相对于只能处理单一的atomic操作,这些class能够让多个操作被atomic地对待,这样我们也就有可能不需要同步就能实现同步机制所做到的一切。
      我们可以用AtomicInteger,AtomicLong,AtomicBoolean和AtomicReference这四个class实现的四个基本的atomic类型来处理integer,long,boolean和对象。这些class都提供了两个构造器:默认的构造器的值为0,false,false或者null,另一个构造器是以程序设计者所指定的值来初始化和创建变量。set()和get()这两个方法就提供了volatile变量所具有的的功能:能够atomic的设定与取得值,因为它们能够确保数据的读写是从主存储器上运行的。但是这些class还提供了更多的操作来适应volatile无法解决的情况。
      getAndSet()能够在返回初始值的时候atomic的设定变量成新值,完全不需要任何的同步lock。compareAndSet()与weakCompareAndSet()是有条件的修改程序的方法,这两个方法都要取用两个参数:在方法启动时预期数据所具有的的值,以及要把数据所设定成的值。它们都只会在变量具有预期值的时候才会设定成新值,如果当前值不等于预期值,该变量就不会被重新赋值并且返回false。这两个方法之间有什么区别吗?第二个方法少了一项保证:如果方法返回的值false,该变量不会被变动,但是这并不表示现有值不是预期值,也就是说,这个方法不管初始值是否是预期值都可能会无法更新改值。
      incrementAndGet(),decrementAndGet(),getAndIncrement()和getAndDecrement()提供了前置递增,前置递减,后递增和后递减,之所以有这些方法,是因为这些操作都不是atomic的。
      addAndGet()和getAndAdd()提供了"前置"和"后置"的运算符给指定值的加法运算,它们能够让程序对变量增或者减一个指定值,包括了负值,所以我们就不需要一个相对的减法运算。
      atomic package目前没有实现atomic字符或者浮点变量,但是我们可以使用AtomicInteger来处理字符,就像是字符常量一样,但是使用atomic的浮点数需要atomic带有只读浮点数值的受管理对象。我们也没有实现atomic数组,并没有功能能够对整个数组做atomic化的变动,最多就是通过使用AtomicInteger,AtomicLong和AtomicReference的数组来模型化,但是数组的大小必须在构造时就指定好,并且在操作过程中必须提供索引。至于Boolean的atomic数组,同样也可以通过AtomicInteger来实现。
     atomic package还有两个类:AtomicMarkableReference和AtomicStampedReterence。这两个类能够让mark或stamp跟在任何对象的引用上,更精确点讲,AtomicMarkableReference提供了一种包括对象引用结合boolean的数据结构,而AtomicStampedReference提供了一种包括对象引用结合integer的数据结构。
     其实,atomic class的这些方法在本质上是一样的。在使用的时候,get()方法需要我们传入一个数组作为参数,stamp或者mark被存储在数组的第一个元素而引用被正常返回。其他的get()方法就只是返回引用,mark或者stamp。
    set()与compareAndSet()方法需要额外的参数来代表mark或者stamp。最后,这些class都带有attemptMark()或attemptStamp()方法,用来依据期待的引用设定mark或者stamp。  

0 0
原创粉丝点击