使用原子整数时的竞争条件

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() 。