Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is lazySet in Java's Atomic* classes implemented?

In this video about Disruptor, a concurrency framework, the lazySet method of Java's Atomic* classes (e.g. AtomicLong) is mentioned. According to the documentation, this method "eventually sets to the given value".

Does anybody know what the underlying mechanism is to implement this (specifically on x86 on Windows, if that is relevant). It can't be InterlockedExchange(), because that would set the value and make sure cache lines are flushed before returning, if I'm not mistaken.

like image 747
PersonalNexus Avatar asked Dec 05 '11 05:12

PersonalNexus


2 Answers

This basically calls to unsafe.putOrderedLong() which is a native function. Based on the distinction made in unsafe between ordered (lazy) vs volatile (immediate). I am nearly certain that the (lazy) version simply resolves to a storestore while volatile requires the more expensive loadstore. This preserves threading semantics (for the setting thread) without halting all other cores. Eventually the readers will pickup the new value.

[Edit: That said (which is speculative), I am certain that the lazy store uses 'lighter' memory fencing that used by the full volatile -- if the platform provides it. E.g. I don't see what you can't do the same in C#, say for x86]

Typical use of something like this is a counter (say queue depth). If you hit a volatile on every iteration, it will not be "high performance" as you incur the full cost of cache coherence in each iteration. If your concurrent interaction permits 'fuzzy' readings then your (interacting via memory) then this technique reduces the cost of maintaing total system state (within an acceptable range of error e.g. your reading of queue depth is a bit off.)

[p.s./edit: discussion of fencing by Distruptor's designers.]

like image 102
alphazero Avatar answered Oct 23 '22 04:10

alphazero


Found this description of the implementation in Bug 6275329:

The semantics are that the write is guaranteed not to be re-ordered with any previous write, but may be reordered with subsequent operations (or equivalently, might not be visible to other threads) until some other volatile write or synchronizing action occurs).

...

For people who like to think of these operations in terms of machine-level barriers on common multiprocessors, lazySet provides a preceeding store-store barrier (which is either a no-op or very cheap on current platforms), but no store-load barrier (which is usually the expensive part of a volatile-write)

like image 45
PersonalNexus Avatar answered Oct 23 '22 05:10

PersonalNexus