我定义了以下实例变量:
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 ?
我想避免使用同步。
答案 0 :(得分:2)
您可以想到
tradeCounter.incrementAndGet();
和
System.out.println();
作为两个单独的语句。 所以在这里
System.out.println(tradeCounter.incrementAndGet());
基本上有两个语句,而且这些语句不是原子的。
想象一下这样的示例,它有2个线程:
tradeCounter.incrementAndGet()
tradeCounter.incrementAndGet()
这完全取决于线程在您的方法中调用指令的顺序。
答案 1 :(得分:2)
我有一个名为onTrade的方法,定义如下,被6调用 线程:
public void onTrade(Trade trade) { System.out.println(tradeCounter.incrementAndGet()); }
为什么输出:
2 5 4 3 1 6
代替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);
}
或者,不用担心输出的打印顺序。考虑:出于某种原因,输出顺序实际上有意义吗?
答案 2 :(得分:1)
incrementAndGet()
按预期顺序增加:1、2、3等...
但是system.out
不会像println()
那样以原子方式调用incrementAndGet()
。因此,可以预期随机排序。
我想避免使用同步。
在这种情况下您无法执行。
答案 3 :(得分:1)
System.out.println(...)和tradeCounter.incrementAndGet()是两个单独的操作,最有可能在线程i获得新值时,某些其他线程可以获取值并在线程i打印之前将其打印。在这里无法避免同步(直接或间接)。