咱们首先看一个例子:产生一个整数序列,每一个值都必须是递增惟一的。咱们能够用如下代码实现一个:java
public class UnsafeSequence{ private int value; public int getNext(){ return value++; } }
上面的代码在单线程环境下运行没有任何问题,可是若是在多线程并发访问的状况下它就会有问题。仔细分析getNext方法实际上它包含了三步操做:安全
第一步:得到当前value值;多线程
第二步:把当前value值+1;并发
第三步:返回当前value值。高并发
多个线程并发执行上面方法时,返回的value值极有多是相同的,这显然违背了咱们的初衷,因此这个类不是线程安全的。以下图所示:工具
咱们能够用前面讲到的加锁知识把该类修改为线程安全的,最简单的就是给方法加synchronized;atom
public class SafeSequence{ private int value; public synchronized int getNext(){ return value++; } }
修改完之后这个类如今是线程安全的了。若是有线程正在执行getNext方法,那么其余线程就等待当前线程执行完毕后再执行,这样就保证了整个操做的原子性。当这样作仍是会给开发人员带来额外的负担,开发人员不得不去思考在哪些调用是须要共享的,同时还得避免死锁以及其余活跃性问题。因而,Java 5以后java.util.concurrent.atomic包下面的支持原子操做的类便诞生了。spa
java.util.concurrent.atomic包下面有不少支持以原子方式更新的类,比较经常使用的有:AtomicBoolean,AtomicInteger,AtomicLong和AtomicReference<V>。咱们就以AtomicInteger类为例,讲讲它的用法:线程
仍是上面的产生一个整数序列的例子,要求序列值惟一,用AtomicInteger就能够很容易实现。code
AtomicInteger ai = new AtomicInteger(); ai.incrementAndGet();
代码是否是很简洁,他一样线程安全的实现了一个惟一序列,使用起来更加方便和简单。AtomicInteger有两个构造方法,同时提供了不少其余支持原子操做的方法,
public class AtomicInteger{ public int addAndGet(int delta);//以原子方式将给定值与当前值相加, public int getAndAdd(int delta); public int decrementAndGet();//以原子方式将当前值减1,相似i--,--i public int getAndDecrement(); public int getAndIncrement();//以原子方式将当前值加1,相似i++,++i public int incrementAndGet(); public int get();//获取当前值 public void set(int value);//设置给定值 public void lazySet(int newValue);//最终设置某值 ………… }
看了这些方法的方法名我想你就已经明白了如何使用他们。AtomicBoolean,AtomicLong和AtomicReference<V>的使用与AtomicInteger相似,能够经过查看API了解他们的具体方法。
原子类的出现简化了咱们程序中的原子操做,使程序更加安全稳固。并且,在高并发的场景下,原子类的执行效率也要高于加锁的原子操做。所以,若是在项目中有相似的功能,不妨就试试java提供的原子工具类。