1,在多线程中我们知道一个问题就是i++操作时,我们得到的结果和我们想象的结果不一样,因为i++操作会被分成三步。分别是取值,++操作,赋值(读,改,写)。当线程执行到取值或者++操作时,线程突然切换,所以最终得到的结果可能有些奇怪!看看下面程序
创建是个线程对i进行++操作
public class AtomicTest {
public static void main(String[] args) {
AtomicDemo ad = new AtomicDemo();
for(int i=0; i<10; i++) {
new Thread(ad).start();
}
}
}
class AtomicDemo implements Runnable {
private volatile int i = 0; //volatile保证可见性
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+getI());
}
public int getI() {
return i++;
}
}
运行结果
解决方法
jdk1.5后java.util.concurrent.atomic包提供了常用的原子操作
1,volatile 保证内存可见性
2,CAS:保证数据原子性 unsafe
CAS是硬件对于并发操作共享数据的支持,包含了三个操作数
内存值 V 预期值 A 更新值 B
当且仅当V==A时 才更新值 否则不做任何操作
使用Atomic操作
public class AtomicTest {
public static void main(String[] args) {
AtomicDemo ad = new AtomicDemo();
for(int i=0; i<10; i++) {
new Thread(ad).start();
}
}
}
class AtomicDemo implements Runnable {
AtomicInteger a = new AtomicInteger(0);
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+getI());
}
public int getI() {
return a.getAndIncrement(); /类似/a++
}
这样就可以保证i++问题了