[concurrency-interest] Suggestion: .hardGet() for atomic variables

Raph Frank raphfrk at gmail.com
Thu Jan 19 15:10:01 EST 2012


I gave more detail in the thread "Volatile happens before question".

It is for an optimistic read situation

The write is:

W1: sequenceCounter.increment()
W2: <modify the non-volatile memory>
W3: sequenceCounter.increment()

The increment makes the counter an odd number and the 2nd one sets it
back to even.

The read is:

R1: sequenceCounter.get()
R2: <read from non-volatile memory>
R3: sequenceCounter.get()

If the 2 reads give the same value (no sequence update) and it is even
(wasn't unstable), then R2 is assumed to have read correctly.

Otherwise, the read is considered to have failed.

------

However, it doesn't technically work.

R1, R3, W1 and W3 are changes to volatile variables (an AtomicInteger)
so they have to be sequenced somehow.

The danger sequence is this one:

R1 (volatile read)
R3 (volatile read)
W1 (volatile read/write)
W3 (volatile read/write)

Since R3 happens before W1, the 2nd read is even (still at the initial
value of 0), and therefore the read is considered to have read stable
data.

The happens before relationships are

R1 happens-before R2 happens-before R3
W1 happens-before W2 happens-before W3

However, since W1 is a write and R3 is a read, there is no happens
before relationship.

This means that R2 and W2 have no happens-before relationship and
effectively happen concurrently and there is a data race.

------

The code could be changed so that it works by using

The read is:

R1: sequenceCounter.get()
R2: <read from non-volatile memory>
R3: sequenceCounter.getAndAdd(0) [*]

[*] This assumes that adding zero still causes the write to be
considered to have happened

------

The sequence is this one:

R1 (volatile read)
R3 (volatile read/write)
W1 (volatile read/write)
W3 (volatile read/write)

Since R3 is now a write and W1 is a read, R3 happens before W1 and
therefore R2 happens before W2, so they execute in sequence.

.hardGet() would be equivalent to .getAndAdd(0), but would work for
the non-numeric Atomic types.


More information about the Concurrency-interest mailing list