puzzled when using synchronized lock

98 Views Asked by At

See below code, this puzzles me, in class DynamicPropertyFactory, it locks ConfigurationManager.class, as my understanding, the lock works only in the class or the instance itself. How to understand this?

public class *DynamicPropertyFactory*{
      public static *DynamicPropertyFactory* initWithConfigurationSource(AbstractConfiguration config) {
            synchronized (**ConfigurationManager.class**) {
                if (config == null) {
                    throw new NullPointerException("config is null");
                }
                if (ConfigurationManager.isConfigurationInstalled() && config != ConfigurationManager.instance) {
                    throw new IllegalStateException("ConfigurationManager is already initialized with configuration "
                            + ConfigurationManager.getConfigInstance());
                }
                if (config instanceof DynamicPropertySupport) {
                    return initWithConfigurationSource((DynamicPropertySupport) config);
                }
                return initWithConfigurationSource(new ConfigurationBackedDynamicPropertySupportImpl(config));
            }
        }
    }
3

There are 3 best solutions below

1
Azodious On

as my understanding, the lock works only in the class or the instance itself

This is wrong and unclear what you want to say.

lock can be taken on any reference which is not pointing to null.

synchronized (ConfigurationManager.class)

this line means that on class object lock is being taken.

2
Igor Perciuleac On

In this case lock on ConfigurationManager.class works like global monitor.

If you put the same lock in to ConfigurationManager instance then it will synchronize all threads, which deal each instance of ConfigurationManager.

1
Danikov On

This question is highly relevant; remember that the target of your synchronized(target) is the thing that manages the mutual exclusivity of the code block. Only one thread can execute the code block at any given time, based on whether the monitor of the target is locked, but the target isn't necessarily always the same object.

Everywhere you refer to ConfigurationManager.class in your code should resolve to the same object, so it should work as a universal lock. However, using something like synchronized(this) combined with many instances would result in a lock per instance and some ability for that code to be run in parallel across those instances, just never in parallel on any single instance.

Locking on .class is considered bad practice and you should opt for something like private static final Object lock = new Object(); instead, if you really must have a global lock.