jdk5以后的java.util.concurrent.atomic包里,多了一批原子处理类。主要用于在高并发环境下的高效程序处理。 html
这里,咱们来看看AtomicInteger是如何使用非阻塞算法来实现并发控制的。 java
AtomicInteger的关键域只有一下3个: 算法
Java代码
- // 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。
http://www.cnblogs.com/wenjiang/p/3276433.html