1

I have a Spring bean class that look similar to the following:

@Component
public class Foo{

    private Config conf;

    @PostConstruct
    public void init(){
        conf = ConfigFileLoader.loadConfigFromFile();
    }

    public Config getConfig(){
        return conf;
    }

    public void updateConfig(){
        conf = ConfigFileLoader.loadConfigFromFile();
    } 

}

ConfigFileLoader.loadConfigFromFile() reads configuration from file and returns a new Config object.

There are two types of threads:

  • Updater thread:
    • there is only one
    • it calls updateConfig periodically (when it detects changes on the configuration file)
  • Reader thread:
    • multiple threads are calling getConfig using the Config object for execution.
    • does not care if it receives a stale Config object instance for current execution as long as eventually reader threads start getting an up to date Config object.

My question is this, should i mark the private conf field as volatile or maybe add some kind of synchronisation for conf field?

My fear is the following scenario: the Updater thread updates the conf reference but the change is never made visible to the reader threads.

Any help or explanation will be appreciated.

Dusan.czh
  • 669
  • 8
  • 15
  • 1
    `volatile` work means that when the reference to your variable changes, it will take effect for every thread. So yes, this change will be visible to the reader threads whether you declare it as volatile. – Héctor Aug 13 '15 at 09:52
  • [When volatile is enough][1] [1]: http://stackoverflow.com/questions/106591/do-you-ever-use-the-volatile-keyword-in-java/28235062#28235062 – sujith s Aug 14 '15 at 08:38

2 Answers2

0

The danger here, whether you use volatile or whether you take @sibnick's suggestion and use a ReaderWriterLock, is that some thread will hold on to its own, private reference to a Config object for an extended period of time:

 Config myConfig = foo.getConfig();
 while (conditionThatWillBeTrueForManyIterations()) {
      doSomethingWith(myConfig);
 }

It is impossible to write code that will not keep its own private reference for some period of time because whatever you do with the Config object, you will be doing it outside of the mutex.

Even if you only write this:

doSomethingWith(foo.getConfig());

It is possible that some other thread will update the configuration in between the foo.getConfig() call and the doSomethingWith(...) call.

Your program will have to be able to cope with that possibility.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57
  • There are many possibilities to solve this problem (i.e danger), like making the `Config` Object thread safe (its invariants are kept), or making a defensive copy on each `getConfig()` call, so that no one from outside does not change it. – V G Aug 13 '15 at 14:19
  • For my use case it does not matter that a reader thread will get a stale `Config` object or that it would change in the middle of execution. I am wondering if it is possible that reader threads will **never** see the updated config value since it is not volatile and the writer thread may never update the main memory – Dusan.czh Aug 18 '15 at 06:40
  • 1
    @Dusan.czh, Yes, in your example, it is possible for one thread to call updateConfig(), and then another thread calling `getConfig()` never sees the updated value. Changing the private variable `conf` to be `volatile` will fix that because each call to updateConfig() will assign the volatile variable, and each call to getConfig() will fetch from it. The Java Language Spec promises that _everything_ thread A writes to memory before updating a `volatile` variable will be visible to thread B after B has fetched the same `volatile` variable. – Solomon Slow Aug 18 '15 at 13:18
0

Volatile = An attempt that other threads see the updated value of the object's state , no guarantee that threads run in synch and in a manner that they do not enter a situation that the screw up other's(thread(s) ) work

Synchronized code by intrinsic locks = An attempt to make sure threads see the updated object state + guarantee that threads work in synch and wait for each other so that there is no interference.

The load method you have defined here will have the instruction set which is not atomic .It reads the file and updates the Object it is loaded into.

The read and update operations from a single thread have to be done in a single go in a manner that no other thread interferes and try to redo the same.

Volatile is not a sure shot solution to your issue as your actions are not a single statement /assignment procedure.

Recommendation is to use : intrinsic locks on an object and make read and update method work in synch .

public class Foo{

    private Config conf;
    Object lock = new Object();
    @PostConstruct
    public void init(){
        synchronize(lock)
        {
            conf = ConfigFileLoader.loadConfigFromFile();
        }
    }

    public Config getConfig(){
        synchronize(lock)
        {
            return conf;
        }
    }

    public void updateConfig(){
        synchronize(lock)
        {
            conf = ConfigFileLoader.loadConfigFromFile();
        }
    }

}
Denis Iskhakov
  • 344
  • 1
  • 6
Puneet
  • 113
  • 5