使用AtomicInteger实现共享计数器并发自增的异常问题排查
为什么AtomicInteger自增后线程输出结果不一致?
你的代码里,AtomicInteger的incrementAndGet()确实是原子操作,所以共享计数器的最终值肯定是20000,但输出结果不一致的问题出在return的时机:
- 两个线程并发执行
incrementCounter()方法,每个线程都会循环10000次调用原子自增。 - 假设线程t1先跑完10000次自增,此时它会立刻调用
sharedCounter.get()返回当前值——这时候线程t2可能已经执行了一部分自增(比如3000次),所以t1返回的就是10000+3000=13000。 - 等t2把剩下的7000次自增做完,再调用
get()的时候,计数器已经被两个线程总共增到20000了,所以t2返回20000。 - 反过来,如果t2先跑完自己的循环,t1还在执行,那t2返回的就是10000加上t1已经完成的次数,t1最后返回20000。
另外要说明:你给AtomicInteger加的volatile是多余的——AtomicInteger内部通过Unsafe类的CAS操作已经保证了值的可见性和原子性,不需要额外用volatile修饰。
如果想让两个线程都输出20000,可以调整代码逻辑:不要在每个线程的方法里返回并输出,而是等两个线程都执行完毕后,在main方法里统一获取并打印最终值:
class MyCounterClass{ AtomicInteger sharedCounter = new AtomicInteger(0); public void incrementCounter() { for(int i = 0; i <10000; i++){ sharedCounter.incrementAndGet(); } } } public static void main(String[] args) throws InterruptedException { MyCounterClass myCounterClassObj = new MyCounterClass(); Thread t1 = new Thread(myCounterClassObj::incrementCounter); Thread t2 = new Thread(myCounterClassObj::incrementCounter); t1.start(); t2.start(); t1.join(); t2.join(); // 所有线程执行完后再获取最终值 System.out.println("最终计数器值:" + myCounterClassObj.sharedCounter.get()); }
内容的提问来源于stack exchange,提问作者Mausumi
相关产品推荐
相关产品推荐

