3

Is it safe to assume that the code before (AtomicInteger a).addAndGet(-1) will be always executed before this call, i.e. JVM will not reorder the instructions around the addAndGet call?

If yes, is it safe to assume that other threads checking the state of the same AtomicInteger instance (e.g. if (a.compareAndSet(0, -1))) will see everything the first thread has changed before the addAndGet call?

Gedrox
  • 3,592
  • 1
  • 21
  • 29
  • I believe that you can only rely on the fact that set happens-before get on that specific AtomicInteger. – Andy Turner Sep 24 '15 at 15:20
  • 1
    To be nitpicking, you never have any guarantees about when something is executed, but about the *observable effects*. But that’s actually what you are interested in. You shouldn’t ignore that within `if(a.compareAndSet(…))` you will only be guaranteed to see the changes made by the thread(s) which turned the value into the expected value. So you have to ensure that there are not multiple ways to get to that value… – Holger Sep 25 '15 at 12:51
  • @Holger, what might help in this situation? I must see changes of all threads which decreased the value of `a` and the last thread which makes it zero must work with data collected from all the threads. – Gedrox Sep 25 '15 at 14:42
  • That’s no problem as long as there are *exactly* as many threads as needed to decrease the value to zero. You *must not* have threads which could increase the number again (before zero was detected) and *not* more threads than necessary. E.g. if you start with `a=5` and have six decreasing threads, by reaching zero, one thread might be out of sync and you don’t know which one. But if you have exactly five decreasing threads, you know that all must have passed the barrier… – Holger Sep 25 '15 at 14:53

1 Answers1

6

Is it safe to assume that the code before (AtomicInteger a).addAndGet(-1) will be always executed before this call, i.e. JVM will not reorder the instructions around the addAndGet call?

Yes, that's right. The addAndGet will issue a volatile store (or similar) and as such other loads and stores cannot be reordered beneath it.

edit: Thanks Soitrios for linking https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html, this indicates there is an establishment of ordering for you.

  • get has the memory effects of reading a volatile variable.
  • set has the memory effects of writing (assigning) a volatile variable.
  • compareAndSet and all other read-and-update operations such as getAndIncrement have the memory effects of both reading and writing volatile variables.
John Vint
  • 39,695
  • 7
  • 78
  • 108
  • 1
    Not only is the JVM prevented from doing the, the CPU is prevented as well. i.e. the CPU can re-order the executution of instructions as well. – Peter Lawrey Sep 24 '15 at 19:00
  • @John Vint, do you agree with the @Holger comment above about "within `if(a.compareAndSet(…))` you will only be guaranteed to see the changes made by the thread(s) which turned the value into the expected value"? – Gedrox Sep 25 '15 at 14:56
  • Yes, I do agree with that statement. Since we cannot say that a failing thread successfully wrote, it never issues a volatile store. And as such there is no synchronization between that thread's writes and a successive thread's reads. – John Vint Sep 25 '15 at 14:59