volatile可以保证所有线程看见的值都是最新的,atomic可以保证+-的原子性操作。
每个线程都有自己独立的数据块,对于共享变量,它们先将其拷贝到自己的内存空间,创建一个副本,之后再进行的操作针对的都是副本,最后在线程退出前的某一时刻把值再放回到共享变量中。而volatile保证了每次在线程内存空间中副本的变化都会直接映射到共享内存之中,使共享内存中的变量值始终为最新的。
但volatile对于如下情况便会失效:
T1 load i
T2 load i
T1 store i+1
T2 store i+1
两个线程对i进行操作,本意是实现i=i+2,但最后只实现了i=i+1。
面对这种情况,可以使用atomic类,它在volatile的基础之上,实现了+-的原子性操作。即当多线程访问时,变量的+-与赋值两步变为了一步操作。
AtomicInteger atomicInteger = new AtomicInteger(5);
atomicInteger.incrementAndGet();
atomicInteger.getAndIncrement();
atomicInteger.addAndGet(5);
atomicInteger.getAndAdd(5);
atomicInteger.getAndDecrement();
atomicInteger.decrementAndGet();
getAndAdd与addAndGet的区别就是i++与++i的区别。
总结:
atomic比volatile更靠谱,但volatile比atomic开销小。