原子整数值未在线程中更新
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.
我在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.