原子整数计数器以错误的顺序打印
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 调用
tradeCounter.incrementAndGet()
- 线程 2 调用
tradeCounter.incrementAndGet()
- 线程 2 打印值 2
- 线程 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);
}
或者,不必担心输出的打印顺序。考虑:出于任何原因,输出顺序是否真的有意义?
我定义了以下实例变量:
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 调用
tradeCounter.incrementAndGet()
- 线程 2 调用
tradeCounter.incrementAndGet()
- 线程 2 打印值 2
- 线程 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);
}
或者,不必担心输出的打印顺序。考虑:出于任何原因,输出顺序是否真的有意义?