原子整数计数器以错误的顺序打印

atomic integer counter printing in wrong order

我定义了以下实例变量:

private final AtomicInteger tradeCounter = new AtomicInteger(0);

我有一个名为 onTrade 的方法,定义如下,被 6 个线程调用:

public void onTrade(Trade trade) {
    System.out.println(tradeCounter.incrementAndGet());
}

为什么输出是:

2 5个 4个 3个 1个 6

而不是 1个 2个 3个 4个 5个 6个 ?

我想避免使用同步。

incrementAndGet() 按预期顺序递增:1、2、3 等... 但是 system.out 不会沿 incrementAndGet() 以原子方式调用 println()。所以随机排序是意料之中的。

I want to avoid using synchronization.

在这种情况下你不能。

你可以想到

tradeCounter.incrementAndGet();

System.out.println();

作为两个单独的语句。 所以这里

System.out.println(tradeCounter.incrementAndGet());

基本上有两个语句,这些语句加在一起不是原子的。

想象这样一个有 2 个线程的例子:

  1. 线程 1 调用 tradeCounter.incrementAndGet()
  2. 线程 2 调用 tradeCounter.incrementAndGet()
  3. 线程 2 打印值 2
  4. 线程 1 打印值 1

这完全取决于线程在您的方法中调用指令的顺序。

System.out.println(...) 和 tradeCounter.incrementAndGet() 是两个独立的操作,很可能当 thread-i 获取新值时,其他一些线程可以获取值并在之前打印它thread-i 打印它。这里无法避免同步(直接或间接)。

I have a method called onTrade defined as below being called by 6 threads:

public void onTrade(Trade trade) {
    System.out.println(tradeCounter.incrementAndGet());
}

Why is the output:

2 5 4 3 1 6

Instead of 1 2 3 4 5 6 ?

为什么不应该输出?或者为什么不是 3 1 4 6 5 2?或者 1 2 3 4 5 6 的任何其他排列?

使用 AtomicInteger 及其 incrementAndGet() 方法可确保每个线程获得不同的值,并且获得的六个值是连续的,没有同步。但这与随后打印结果值的顺序没有任何关系

如果您希望结果以与获取结果相同的顺序打印,那么同步是最简单的方法。在这种情况下,使用 AtomicInteger 与使用普通 int 相比没有任何好处(为此特定目的):

int tradeCounter = 0;

synchronized public void onTrade(Trade trade) {
    System.out.println(++tradeCounter);
}

或者,不必担心输出的打印顺序。考虑:出于任何原因,输出顺序是否真的有意义?