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

问题描述

我在课堂上定义了一个atomicinterger变量。该类还扩展了线程类。我创建了两个线程,并在run方法增加了原子整数的值。我在运行两个线程后排除了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();
,

您说:

如果仍然有一个静态整数,我仍然会感到困惑,因为我可以在所有线程上看到相同的数据,并且可以实现线程安全性

您误会了。不,你不能。

VM基本上是这样的:

对于任何给定的字段,所有线程都具有该字段的本地副本,并且它们都有不公平的硬币。他们在读取或写入时随时翻转它。如果硬币落在正面,他们将同步该字段并对其进行读写。如果硬币落在尾巴上,则它们会读取/写入副本。代币不公平,因为它会惹上您:在测试期间和在您的机器上始终翻转头,在向该重要客户进行演示时,几次反复甩尾。

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

x = x + 1;

和另一个线程中的相同代码,x只能递增一次,因为第二个线程读取了它的克隆副本,因此第一个线程的增量被忽略了。或不。也许今天您尝试了100次,而每次的结果却增加了+2。然后,winamp上的下一首歌曲开始,或者月亮的相位发生变化,现在看来它只能可靠地加1。这一切都可能发生,这就是这种代码从根本上被破坏的原因。 除非您已经非常小心地简化了该字段,否则请勿与多个线程中的一个字段进行交互

除非建立所谓的先有后继关系,否则您不能强行使用硬币。您可以通过使用volatile或sync,或通过调用执行此操作的代码来执行此操作。它变得复杂。很快。

AtomicInteger是另一种解决方案。这是原子的。如果您的线程具有:

atomicInt.incrementAndGet();

和另一个具有相同功能的对象,在它们都运行之后,保证atomicInt已经增加了2。