1.java.util.concurrent.atomic 的包里有AtomicBoolean, AtomicInteger,AtomicLong,AtomicLongArray,
AtomicReference等原子类的类,主要用于在高并发环境下的高效程序处理,来帮助咱们简化同步处理.java
在Java语言中,++i和i++操做并非线程安全的,在使用的时候,不可避免的会用到synchronized关键字。而AtomicInteger则经过一种线程安全的加减操做接口。算法
2.AtomicInteger的基本方法安全
AtomicInteger atomicInteger = new AtomicInteger(123); System.out.println(atomicInteger.get()); --->输出 : 123
AtomicInteger atomicInteger = new AtomicInteger(); System.out.println(atomicInteger.get()); ---->输出: 0
atomicInteger.get(); //获取当前值 atomicInteger.set(999); //设置当前值
atomicInteger.compareAndSet(expectedValue,newValue)并发
public static void main(String[] args) { AtomicInteger atomicInteger = new AtomicInteger(0); System.out.println(atomicInteger.get()); int expectedValue = 123; int newValue = 234; Boolean b =atomicInteger.compareAndSet(expectedValue, newValue); System.out.println(b); System.out.println(atomicInteger); } ----》输出结果为: 0 false 0 public static void main(String[] args) { AtomicInteger atomicInteger = new AtomicInteger(123); System.out.println(atomicInteger.get()); int expectedValue = 123; int newValue = 234; Boolean b =atomicInteger.compareAndSet(expectedValue, newValue); System.out.println(b); System.out.println(atomicInteger); } -----》输出结果为: 123 true 234 由上可知该方法表示,atomicInteger的值与expectedValue相比较,若是不相等,则返回false, atomicInteger原有值保持不变;若是二者相等,则返回true,atomicInteger的值更新为newValue
AtomicInteger atomicInteger = new AtomicInteger(123); System.out.println(atomicInteger.get()); --123 System.out.println(atomicInteger.getAndAdd(10)); --123 获取当前值,并加10 System.out.println(atomicInteger.get()); --133 System.out.println(atomicInteger.addAndGet(10)); --143 获取加10后的值,先加10 System.out.println(atomicInteger.get()); --143
getAndDecrement()和DecrementAndGet()方法app
AtomicInteger atomicInteger = new AtomicInteger(123); System.out.println(atomicInteger.get()); --123 System.out.println(atomicInteger.getAndDecrement()); --123 获取当前值并自减 System.out.println(atomicInteger.get()); --122 System.out.println(atomicInteger.decrementAndGet()); --121 先自减再获取减1后的值 System.out.println(atomicInteger.get()); --121
3.使用AtomicInteger,即便不用同步块synchronized,最后的结果也是100,可用看出AtomicInteger的做用,用原子方式更新的int值。主要用于在高并发环境下的高效程序处理。使用非阻塞算法来实现并发控制。ide
public class Counter { public static AtomicInteger count = new AtomicInteger(0); public static void inc(){ try{ Thread.sleep(1); //延迟1毫秒 }catch (InterruptedException e){ //catch住中断异常,防止程序中断 e.printStackTrace(); } count.getAndIncrement();//count值自加1 } public static void main(String[] args) throws InterruptedException { final CountDownLatch latch = new CountDownLatch(100); for(int i=0;i<100;i++){ new Thread(new Runnable() { @Override public void run() { Counter.inc(); latch.countDown(); } }).start(); } latch.await(); System.out.println("运行结果:"+Counter.count); } } 运行结果: 100
4.使用普通Integer高并发
public class Counter { public volatile static int count = 0; public static void inc(){ try{ Thread.sleep(1); //延迟1毫秒 }catch (InterruptedException e){ //catch住中断异常,防止程序中断 e.printStackTrace(); } count++;//count值自加1 } public static void main(String[] args) throws InterruptedException { final CountDownLatch latch = new CountDownLatch(100); for(int i=0;i<100;i++){ new Thread(new Runnable() { @Override public void run() { Counter.inc(); latch.countDown(); } }).start(); } latch.await(); System.out.println("运行结果:"+Counter.count); } } 运行结果:98
5.若是在inc方法前面加个synchronized也能是线程安全的;工具
它用来修饰一个方法或者一个代码块的时候,可以保证在同一时刻最多只有一个线程执行该段代码。this
import java.util.concurrent.CountDownLatch; /** * created by guanguan on 2017/10/23 **/ public class Counter { public volatile static Integer count = 0; public synchronized static void inc(){ try{ Thread.sleep(1); //延迟1毫秒 }catch (InterruptedException e){ //catch住中断异常,防止程序中断 e.printStackTrace(); } count++;//count值自加1 } public static void main(String[] args) throws InterruptedException { final CountDownLatch latch = new CountDownLatch(100); for(int i=0;i<100;i++){ new Thread(new Runnable() { @Override public void run() { Counter.inc(); latch.countDown(); } }).start(); } latch.await(); System.out.println("运行结果:"+Counter.count); } } 运行结果:100
synchronized的使用说明:atom
1、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程获得执行。另外一个线程必须等待当前线程执行完这个代码块之后才能执行该代码块。 2、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另外一个线程仍然能够访问该object中的非synchronized(this)同步代码块。 3、尤为关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其余线程对object中全部其它synchronized(this)同步代码块的访问将被阻塞。 4、第三个例子一样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就得到了这个object的对象锁。结果,其它线程对该object对象全部同步代码部分的访问都被暂时阻塞。 5、以上规则对其它对象锁一样适用.
6.从上面的例子中咱们能够看出:使用AtomicInteger是很是的安全的.并且由于AtomicInteger由硬件提供原子操做指令实现的。在非激烈竞争的状况下,开销更小,速度更快。
java的关键域有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可能已经被其余线程更新了)。
这里,咱们以自增的代码为例,能够看到这个并发控制的核心算法:
源码 public final int updateAndGet(IntUnaryOperator updateFunction) { int prev, next; do { prev = get(); next = updateFunction.applyAsInt(prev); } while (!compareAndSet(prev, next)); return next; }