版权声明:Please make the source marked https://blog.csdn.net/qq_31807385/article/details/83997108
先看下面的案例:
package hello_java;
public class Automic {
public static void main(String[] args) throws InterruptedException {
ShareData03 shareData03 = new ShareData03();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
shareData03.produce();
}
},"A");
thread1.start();
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
shareData03.consume();
}
},"B");
thread2.start();
thread1.join();
thread2.join();
System.out.println("count 的值为:" + shareData03.count);
}
}
class ShareData03{
public int count = 0;
public void produce(){
count ++;
}
public void consume(){
count --;
}
}
count 的值为:0
现在我们把循环的的值从10 改到100000,(可以改的更大,这样效果更佳明显,错误也更容易出现)。
count 的值为:-1956
为什么会 出现这样的错误呢?
++ 和 -- 操作不是原子性的,中间可能会 被其他的指令打断。
关于这一点,可以参考下面的这个blog:
好的,接下来我们说说这个问题的解决方法:
package hello_java;
import java.util.concurrent.atomic.AtomicInteger;
public class Automic {
public static void main(String[] args) throws InterruptedException {
ShareData03 shareData03 = new ShareData03();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 100000; i++) {
shareData03.produce();
}
},"A");
thread1.start();
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 100000; i++) {
shareData03.consume();
}
},"B");
thread2.start();
thread1.join();
thread2.join();
System.out.println("count 的值为:" + shareData03.count);
}
}
class ShareData03{
public AtomicInteger count = new AtomicInteger(0);
public void produce(){
count.incrementAndGet();
}
public void consume(){
count.decrementAndGet();
}
}
count 的值为:0
这个解决的方法是在jdk1.5之后在juc中出现的很多的原子类中的一个,这些原子类都使用了CSA算法。其中的
incrementAndGet 和 decrementAndGet 的源码我们打开看看,其使用了CSA:更底层使用的是 compareAndSwapInt ( CAS算法)
该算法会不断的轮询()循环),以获得最新的数据值。如下图: