在java中,对基本数据类型的变量的读取和复制操作是原子性操作。
但是像x++,y=x , 诸如此类的操作却不是原子性的需要考虑并发问题(原因见多线程环境中的原子操作)。
对此类操作同步问题,可以采用synchronization,lock 等方法解决,但是这边介绍concurrency package 下的AtomicInteger。
Java AtomicInteger Example
package com.marshall.atomic;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class JavaAtomic {
public static class ProcessingThread implements Runnable {
private AtomicInteger count = new AtomicInteger();
public void run() {
for(int i=0;i<5;i++){
processSth(i);
count.incrementAndGet();
}
}
public int getCount(){
return this.count.get();
}
private void processSth(int i){
//process some job
try {
TimeUnit.SECONDS.sleep(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
ProcessingThread pt=new ProcessingThread();
Thread t1=new Thread(pt,"t1");
Thread t2=new Thread(pt,"t2");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Process count:"+pt.getCount());
}
}
执行结果:
AtomicInteger 已经确保了incrementAndGet操作的原子性, 所以在我们在使用incrementAndGet 无需考虑多线程下的实现的细节。
最后总结下, concurrency 包下 AtomicInteger 相对于使用常规synchronize 的优点。
- 由于封装了同步的细节,代码更加简洁易读,并且减少了出错的可能性
- 在性能上, 也比synchronization 更好。
底层采用了CAS保证同步, 本质是一种乐观锁,而synchronized 的实现是基于悲观锁