public class Test implements Runnable {
private static volatile int count = 0 ; //使用 volatile 修饰基本数据内存不能保证原子性
//private static AtomicInteger count = new AtomicInteger() ;
public void run() {
for (int i=0;i<10000 ;i++){
count ++ ;
//count.incrementAndGet() ;
}
}
public static void main(String[] args) throws InterruptedException {
Test volatileInc = new Test() ;
Thread t1 = new Thread(volatileInc,"t1") ;
Thread t2 = new Thread(volatileInc,"t2") ;
t1.start();
//t1.join();
t2.start();
//t2.join();
for (int i=0;i<10000 ;i++){
count ++ ;
//count.incrementAndGet();
}
System.out.println("最终Count="+count);
}
}
当我们三个线程(t1,t2,main)同时对一个 int 进行累加时会发现最终的值都会小于 30000。
这是因为虽然
volatile保证了内存可见性,每个线程拿到的值都是最新值,但count ++这个操作并不是原子的,这里面涉及到获取值、自增、赋值的操作并不能同时完成。
-
所以想到达到线程安全可以使这三个线程串行执行(其实就是单线程,没有发挥多线程的优势)。
-
也可以使用
synchronize或者是锁的方式来保证原子性。 -
还可以用
Atomic包中AtomicInteger来替换int,它利用了CAS算法来保证了原子性。
本文探讨了在多线程环境下,三个线程对同一数值进行累加时出现的最终结果小于预期的问题。分析了volatile关键字无法确保操作原子性的原因,并提出了通过串行执行、使用synchronized或Lock实现原子性,以及利用AtomicInteger类的CAS算法来解决线程安全问题。
9023

被折叠的 条评论
为什么被折叠?



