You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
`private volatile int a;
public static void main(String[] args){
CasTest casTest=new CasTest();
new Thread(()->{
for (int i = 1; i < 5; i++) {
casTest.increment(i);
System.out.print(casTest.a+" ");
}
}).start();
new Thread(()->{
for (int i = 5 ; i <10 ; i++) {
casTest.increment(i);
System.out.print(casTest.a+" ");
}
}).start();
}
`private volatile int a; public static void main(String[] args){ CasTest casTest=new CasTest(); new Thread(()->{ for (int i = 1; i < 5; i++) { casTest.increment(i); System.out.print(casTest.a+" "); } }).start(); new Thread(()->{ for (int i = 5 ; i <10 ; i++) { casTest.increment(i); System.out.print(casTest.a+" "); } }).start(); }
Activity
LilRind commentedon May 7, 2025
我认为这个代码的主要问题是在:increment 和打印操作不是原子性的。
原本代码是想模拟多个线程争抢并修改共享变量的场景。因为线程2在a=4之前是一直循环的,虽然不能修改a,要等到线程1修改a=4。
代码主要是在打印时机、线程调度上有问题:
因为increment 和打印操作不是原子性的。
如果从性能上来说,就是线程执行顺序不确定,会增加CPU消耗:虽然while+CAS本身就是会消耗CPU,但可以优化。
所以,运行的结果可能就会是这样:
线程1 依次将 a 更新为 1,2,3,并打印 1,2,3。
线程1 执行 increment(4),将 a 更新为 4。
在线程1 打印 a 之前,线程2 执行 increment(5),将 a 更新为 5。
线程1 打印 a,此时 a=5,输出 5。
线程2 继续执行 increment(6) 到 increment(9),将 a 更新为 6,7,8,9,并打印 6,7,8,9。
最终输出:1,2,3,5,5,6,7,8,9。
可以改进如下:
还有一种方法是用AtomicInteger的compareAndSet(),但是它是包装了的工具类(经过设计过后的),需要理解原理:
Snailclimb commentedon May 8, 2025
感谢,很不错的分析👍我已对原文进行修正。
zkj12321 commentedon Dec 10, 2025
@Snailclimb 修改后的代码,也就是目前的代码是否存在输出
1 2 3 5 4 6 7 8 9的可能性,也就是t1线程在执行最后一次casTest.incrementAndPrint(4)但是还没有来得及输出4,就被t2线程抢占处理机,先输出出来5,导致上面的情况。如果这种可能有的话,那么4会有在5~9之后任意一个位置输出的可能性。smlsix commentedon Jul 31, 2026
有道理