I have a cache which I implemented using a simeple HashMap. like -
HashMap<String,String> cache = new HashMap<String,String>();
This cache is used most of the time to read values from it. I have another method which reloads the cache and inside of this method I basically create a new cache and then assign the reference. As I understand assignment of object reference is Atomic in Java.
public class myClass {
private HashMap<String,String> cache = null;
public void init() {
refreshCache();
}
// this method can be called occasionally to update the cache.
public void refreshCache() {
HashMap<String,String> newcache = new HashMap<String,String>();
// code to fill up the new cache
// and then finally
cache = newcache; //assign the old cache to the new one in Atomic way
}
}
I understand that if I do not declare cache as volatile, other threads will not be able to see the changes but it is not time critical for my use case to propagate the change in cache to other threads and they can continue to work with old cache for extended time.
Do you see any threading issue? Consider that many threads are reading from the cache and only at times the cache is reloaded.
EDIT- My main confusion is I do not have to use AtomicReference here as the assignment operation itself is atomic?
EDIT - I understand that to make the ordering proper, I should mark cache as volatile. But If refreshCache method is marked as synchronized, I do not have to make cache as volatile, as Synchronized block will take care of ordering as well as visibility?
First of all, reference assignment is atomic because the specification says so. Besides that, there is no obstacle for JVM implementors to fulfill this constraint, as 64 Bit references are usually only used on 64 Bit architectures, where atomic 64 Bit assignment comes for free.
AtomicReference refers to an object reference. This reference is a volatile member variable in the AtomicReference instance as below. private volatile V value; get() simply returns the latest value of the variable (as volatiles do in a "happens before" manner). public final V get()
AtomicReference toString() method in Java with ExamplesThe toString() method of a AtomicReference class is used to return the String representation of the current value of AtomicReference object.
Atomic is a toolkit of variable java. util. concurrent. atomic package classes, which assist in writing lock and wait-free algorithms with the Java language. An algorithm requiring only partial threads for constant progress is lock-free.
It is not safe without a proper memory barrier.
One would think that the assignment of cache (cache = newCache) would happen after the steps to populate the cache. However, other threads may suffer from reordering of these statements so that the assignment may appear to happen before populating the cache. Thus, it is possible to grab the new cache before it's fully constructed or even worse see a ConcurrentModificationException.
You need to enforce the happens-before relationship to prevent this reordering, and declaring the cache as volatile would achieve that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With