3

I have defined the following instance variable:

private final AtomicInteger tradeCounter = new AtomicInteger(0);

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 ?

I want to avoid using synchronization.

user3809938
  • 1,114
  • 3
  • 16
  • 35

4 Answers4

3

You can think of

tradeCounter.incrementAndGet();

And

System.out.println();

as two separate statements. So here

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

there are basically two statements, and those statements together are not atomical.

Imagine such example with 2 threads :

  1. Thread 1 invokes tradeCounter.incrementAndGet()
  2. Thread 2 invokes tradeCounter.incrementAndGet()
  3. Thread 2 prints value 2
  4. Thread 1 prints value 1

It all depends in what order threads will invoke inctructions in your method.

Michał Krzywański
  • 15,659
  • 4
  • 36
  • 63
2

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 ?

Why shouldn't that be the output? Or why not 3 1 4 6 5 2? Or any of the other permutations of 1 2 3 4 5 6?

Using an AtomicInteger and its incrementAndGet() method ensures that each each thread gets a different value, and that the six values obtained are sequential, without synchronization. But that has nothing to do with the order in which the resulting values are printed afterward.

If you want the results to be printed in the same order that they are obtained, then synchronization is the easiest way to go. In that case, using an AtomicInteger does not gain you anything over using a plain int (for this particular purpose):

int tradeCounter = 0;

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

Alternatively, don't worry about the order in which the output is printed. Consider: is the output order actually meaningful for any reason?

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
1

incrementAndGet() increments in the expected order : 1, 2, 3 etc... But system.out doesn't invoke the println() in an atomic way along incrementAndGet(). So the random ordering is expected.

I want to avoid using synchronization.

You could not in this case.

davidxxx
  • 125,838
  • 23
  • 214
  • 215
1

System.out.println(...) and tradeCounter.incrementAndGet() are two separate operations and most likely when thread-i gets new value, some other threads can get value and print it before thread-i prints it. There is no way to avoid synchronization (direct or indirect) here.

n1t4chi
  • 502
  • 2
  • 12