"class-level" locking, and "object-level" locking are artificial ideas, created by authors who probably do not have a deep understanding of how Java's intrinsic locking works.
class-level locking looks like this:
class Foobar {
static synchronized void moo() { ... }
}
But that construct actually is just a shorthand way of writing:
class Foobar {
static void moo() {
synchronized (Foobar.class) { ... }
}
}
And object-level locking, which looks like this:
class Foobar {
synchronized void baa() { ... }
}
Is nothing but shorthand for:
class Foobar {
static void baa() {
synchronized (this) { ... }
}
}
So really, underneath "class-level" and "object-level" locking, there is only one concept, the synchronized
block:
synchronized(objectReference) {...}
All you need to know is that the JVM will not allow more than one thread to synchronize on the same object at the same time.
When data that you want to protect are global, then it makes sense to synchronize on a global, singleton object while accessing the data. Foobar.class
is a global singleton.
When data that you want to protect are entirely contained within some object instance, then it makes sense to synchronize on something associated with that instance or, on the instance itself (i.e., this
).