原子整数值未在线程中更新

Atomic Integers values are not getting updated in threads

我在class中定义了一个atomicinterger变量。 class 还扩展了线程 class。我创建了两个线程并在 运行 方法中增加了原子整数的值。我在 运行ning 之后排除了 2 的值两个线程,但我得到的值为 1。请告诉我下面的代码出了什么问题。

public class AtomicIntergerTest extends Thread {

    AtomicInteger i = new AtomicInteger();
    int j = 0;

    @Override
    public void run() {
        i.incrementAndGet();

    }

    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub

        AtomicIntergerTest th1 = new AtomicIntergerTest();

        AtomicIntergerTest th2 = new AtomicIntergerTest();

        th1.start();
        th2.start();
        th1.join();
        th2.join();

        System.out.println(th2.i.get());

    }

}

因为 AtomicInteger i = new AtomicInteger(); 每个实例创建一个 AtomicInteger 。你想要

static AtomicInteger i = new AtomicInteger();

你说:

I am still confused if have have a static integer i can get the same data visible across the all threads with that i can achieve my thread safety

你误会了。不,你不能。

虚拟机基本上是这样工作的:

对于任何给定的字段,所有线程都有该字段的本地副本,并且它们都有一个不公平的硬币。他们在读取或写入时随时翻转它。如果硬币正面朝上,他们会同步该字段并 read/write 它。如果硬币反面着地,他们 read/write 副本。硬币是不公平的,因为它会惹恼你:在测试期间和在你的机器上总是抛头,在给重要客户做演示时抛几次反面。

因此,如果我们在一个线程中有此代码 运行:

x = x + 1;

和另一个线程中的相同代码,x 可能只会递增一次,因为第二个线程读取它的克隆副本,因此错过了第一个线程的递增。或不。也许今天你尝试了 100 次,结果每次都是 +2。然后你的 winamp 上的下一首歌曲开始播放或者月相变化,现在它似乎可靠地只加 1。这一切都可能发生,这就是为什么这样的代码从根本上被破坏了。 您不应该与来自多个线程的字段交互,除非您非常小心地简化它

除非你建立so-calledcomes-before或comes-after关系,否则你不能强制硬币。您可以通过使用 volatile 或 synchronized 或调用执行该操作的代码来执行此操作。它变得复杂。快点。

AtomicInteger 是一个不同的解决方案。它是原子的。如果你有一个线程:

atomicInt.incrementAndGet();

和另一个有同样的事情,在他们都运行之后,那个atomicInt已经增加了2,gua运行teed.