首先 , 测试一下正常代码
public class Test1 {
public static int count = 0;
public static void main(String[] args) {
for (int i = 0; i < 10000; i++) {
new Thread() {
public void run() {
count++;
}
}.start();
}
System.out.println("count: " + count);
}
}
输出的结果为count: 9983,这个值不定,每次测试都可能不一样,很显然,100个线程跑++操作,结果并没有像预期的那样count: 10000
接下来换成 volatile修饰count变量
public class Test3 {
static volatile int count = 0;
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 100; i++) {
new Thread() {
public void run() {
for (int j = 0; j < 100; j++) {
count++;
}
}
}.start();
}
Thread.sleep(1000);
System.out.println("volatile count: " + count);
}
}
结果出现volatile count: 9984,果然还是出现问题了,volatile仅仅保证变量在线程间保持可见性,却依然不能保证非原子性的操作。
最后用AtomicInteger类
public class Test2 {
public static AtomicInteger count = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 100; i++) {
new Thread() {
public void run() {
for (int j = 0; j < 100; j++) {
count.getAndIncrement();
}
}
}.start();
}
Thread.sleep(1000);
System.out.println("AtomicInteger count: " + count);
}
}
结果每次都输出"AtomicInteger count: 10000",满足要求
concurrent(我这里是jdk1.8)包下提供了12种原子操作类型
atomic包下提供了AtomicBoolean/AtomicLong/AtomicInteger三个原子更新基本类型,以AtomicInteger为例,其他两种基本类似。以下是AtomicInteger囊括的大致方法
public final int getAndSet(int newValue) //给AtomicInteger设置newValue并返回加oldValue
public final boolean compareAndSet(int expect, int update) //如果输入的值和期望值相等就set并返回true/false
public final int getAndIncrement() //对AtomicInteger原子的加1并返回当前自增前的value
public final int getAndDecrement() //对AtomicInteger原子的减1并返回自减之前的的value
public final int getAndAdd(int delta) //对AtomicInteger原子的加上delta值并返加之前的value
public final int incrementAndGet() //对AtomicInteger原子的加1并返回加1后的值
public final int decrementAndGet() //对AtomicInteger原子的减1并返回减1后的值
public final int addAndGet(int delta) //给AtomicInteger原子的加上指定的delta值并返回加后的值
相应的,concurrent包下除了提供的原子更新基本类型,还有原子更新数据、原子更新引用类型、原子更新字段类,最常用的也就是原子更新基本类型了。