You have not reached the expected behavior. This expression:
cacheData.compareAndSet(null, getDataFromDatabase())
will always call getDataFromDatabase() . This means that it doesn't matter if the data was cached or not. If so, you will still call the database, but discard the results. The cache works, but the performance is equally bad.
Consider this instead:
if(cacheData.get() == null) { cacheData.compareAndSet(null, unmodifiableMap(getDataFromDatabase())); } return cacheData.get());
This is not ideal (still getDataFromDatabase() can be called several times at the beginning), but will work later, as expected. I also moved Collections.unmodifiableMap() earlier so you don't have to transfer the same map again and again.
This leads us to an even simpler implementation (no synchronized or AtomicReference ):
private volatile Map<String, String> cacheData; if(cacheData == null) { cacheData = unmodifiableMap(getDataFromDatabase()); } return cacheData;
source share