I would use AtomicReference
. See my answer to a similar question. Volatile is definitely not enough, because it only guarantees that updates to the variable will be visible to other threads immediately (it effectively disables cached access to it). Concurrent thread access will not be synchronized though, so it could happen that two threads build an updated Set
concurrently, and one of the threads will overwrite the other threads change.
Given two threads T1 and T2 that are running concurrently, imagine the following sequence of events:
- T1 reads variable, current state is V
- T2 reads variable, current state is V
- T1 calculates updated state V×U1
- T2 calculates updated state V×U2
- T1 updates variable to V×U1
- T2 updates variable to V×U2
The final value from the above sequence will be V×U2, so the update U1 is effectively lost.
AtomicReference
on the other hand guarantees that the variable is updated atomically. You'll have to pass in the updater function to the AtomicReference
, so it will be called before atomically storing the result. Make sure you are using a pure function without side effects as the updater function might be called multiple times in case the reference was updated atomically by another thread in the meanwhile.