我正在学习java.util.concurrent.atomic
软件包,并尝试使用Atomic Integer
。根据我的理解,Atomic软件包有助于编写无锁代码,而不是使用同步块。因此,为了测试我的理解,我编写了以下代码:
public class Test{
private final AtomicInteger ai;
public void increment() {
int oldVal = ai.get();
while(!ai.compareAndSet(oldVal, oldVal+1)) {
oldVal = ai.get();
}
}
public int incrementModified() {
return ai.incrementAndGet();
}
public int get() {
return ai.get();
}
public static void main(String[] args) {
Test pc = new Test(5);
Runnable r1 = () -> {
pc.increment();
};
Runnable r2 = () -> {
pc.increment();
};
Runnable r3 = () -> {
pc.increment();
};
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
Thread t3 = new Thread(r3);
t1.start();
t2.start();
t3.start();
System.out.println(pc.get());
}
当我执行上面的代码时,我希望输出为 8 ,但是我得到的输出为 7/8 。然后,我什至使用了内置的incrementAndGet()
方法,并且多次运行该程序后仍然得到相同的输出。
根据我的理解,因为原子可以用作同步块的替代方法,并且通过使用CAS(比较和设置指令)使增量操作成为原子,所以我应该始终将输出设为8。
但是由于我得到的输出不同,所以我假设存在一场比赛,因此o / p在7/8之间变化。
有人可以指出我在上述代码中犯的错误,还是可以纠正我对Java原子类的理解?
编辑:
正如注释中所指出的,我没有使用join()
,因此由于主线程正在请求该值而某些线程可能仍在操作中间,因此得到的结果不正确。我添加了它,并对其进行了多次测试,然后可以看到预期的结果。
答案 0 :(得分:2)
输出值的行与其他3个线程并发执行。如果要确保它在3个线程运行之后执行,则需要在这些线程上加入join()。