使用原子整数时的竞争条件
Race condition while using Atomic Integer
我正在了解 java.util.concurrent.atomic
软件包并尝试使用 Atomic Integer
。根据我的理解,原子包有助于编写无锁代码,而不是使用同步块。所以为了测试我的理解,我写了下面的代码:
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()
方法,并且在多次 运行 程序后仍然得到相同的输出。
根据我的理解,因为 atomic 可以用作同步块的替代方法,并且它通过使用 CAS(比较和设置指令)使增量操作原子化,所以我应该始终将输出设为 8。
但是由于我得到不同的输出,我假设存在一场比赛,因此 o/p 在 7/8 之间变化。
有人可以指出我在上面的代码中犯的错误或纠正我在 Java 中对原子 类 的理解吗?
编辑:
正如评论中指出的那样,我没有使用 join()
,因此得到的结果不正确,因为主线程正在请求该值,而某些线程可能仍在操作中。我添加了它,在测试了很多次之后,我看到了预期的结果。
打印值的行与其他 3 个线程同时执行。如果你想确保它在 3 个线程有 运行 之后执行,那么你需要在这些线程上 join() 。
我正在了解 java.util.concurrent.atomic
软件包并尝试使用 Atomic Integer
。根据我的理解,原子包有助于编写无锁代码,而不是使用同步块。所以为了测试我的理解,我写了下面的代码:
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()
方法,并且在多次 运行 程序后仍然得到相同的输出。
根据我的理解,因为 atomic 可以用作同步块的替代方法,并且它通过使用 CAS(比较和设置指令)使增量操作原子化,所以我应该始终将输出设为 8。
但是由于我得到不同的输出,我假设存在一场比赛,因此 o/p 在 7/8 之间变化。
有人可以指出我在上面的代码中犯的错误或纠正我在 Java 中对原子 类 的理解吗?
编辑:
正如评论中指出的那样,我没有使用 join()
,因此得到的结果不正确,因为主线程正在请求该值,而某些线程可能仍在操作中。我添加了它,在测试了很多次之后,我看到了预期的结果。
打印值的行与其他 3 个线程同时执行。如果你想确保它在 3 个线程有 运行 之后执行,那么你需要在这些线程上 join() 。