Am I synchronizing on the same object instance in the following code? Can I do it safely?
Class Sync {}
Class A implements Runnable {
void run() {
synchronized(Sync.class) {
System.out.println("I am synchronized");
}
}
}
Class B implements Runnable {
void run() {
synchronized(Sync.class) {
System.out.println("I too am synchronized");
}
}
}
Only if they have the same classloader.
If you have a root-classloader and two child-class-loader the two child-class-loader (ie URLClassLoader) load the .class once per classloader, they will work async.
Load
Sync
in the root-classloader will be save.You have to make a distinction between Loading of a
Class
and Resolving aClass
.Class literals and the special method
Class.forName(…)
are different than the methodClassLoader.loadClass(…)
. While aClassLoader
might implement the latter in strange ways, e.g. by returning different instances on each call, the JVM will resolve each class exactly once per context and remember the result.The important point is, if the resolution of a symbolic reference could be redirected, a
static final
variable would not help either. If you have two instances of the sameClass
in your JVM, two different version of theirstatic final
fields would exist as well.There is a one-by-one mapping between a
Class
instance and the JVM per class data.To cite a few official words:
The important point as pointed out by § 5.3.5 is that each
ClassLoader
can define at most one class per unique symbolic name. It might return different instances by delegating to different loaders but then they would be remembered as the defining loader. And the JVM will ask the defining loader when resolving references from aClass
to anotherClass
. Or skip asking it as § 5.3.2 states when aClass
for a given name and loader already exists.According to JLS 8.4.3.6 synchronizing on
Class.forName("name")
and, hence,.class
is the right thing to do and it will work - in the same class, at least. Moreover, all staticsynchronized
methods are synchronized on.class
. As it says in the JLS, the following are virtually the same:However, as JLS 12.2 states, it is not certain when
.class
is called by different classes, since this call depends on the class loader:So if you are using a standard Java class loader - you should be fine. If you are using some custom class loaders, however, you should watch out for errors.