Trying to visualize and understand synchronization.
- What are the differences between using a static lock object (code A) and a non-static lock object (code B) for a synchronized block?
- How does it differ in practical applications?
- What are the pitfalls one would have that the other wouldn't?
- What are the criteria to determine which one to use?
Code A
public class MyClass1 {
private static final Object lock = new Object();
public MyClass1() {
//unsync
synchronized(lock) {
//sync
}
//unsync
}
}
Code B
public class MyClass2 {
private final Object lock = new Object();
public MyClass2() {
//unsync
synchronized(lock) {
//sync
}
//unsync
}
}
Note
The above code shows constructors, but you could talk about how the behavior is different in a static method and a non-static method too. Also, would it be advantageous to use a static lock when the synchronized block is modifying a static member variable?
I already looked at answers in this question, but it's not clear enough what the different usage scenarios are.
The difference is simple: if the locked-on object is in a
static
field, then all instances ofMyClass*
will share that lock (i.e. no two objects will be able to lock on that object at the same time).If the field is non-static, then each instance will have its own lock, so only calls of the method on the same object will lock each other.
When you use a static lock object:
o1.foo()
o1.foo()
, will have to wait for thread 1 to finisho2.foo()
, will also have to wait for thread 1 (and probably 2) to finishWhen you use a non-static lock object:
o1.foo()
o1.foo()
, will have to wait for thread 1 to finisho2.foo()
, it can just continue, not minding thread 1 and 2Which one of those you'll need depends on what kind of data you try to protect with your synchronized block.
As a rule of thumb, you want the lock-object to have the same
static
-ness than the operated-on value. So if you manipulate non-static values only, you'll want a non-static lock object. If you manipulate static values only, you'll want a static lock object.When you manipulate static and non-static values, then it'll become complicated. The easy way would be to just use a static lock object, but that might increase the size of the synchronized-block more than absolutely necessary and might need to more lock contention than desired. In those cases you might need a combination of static and non-static lock objects.
In your particular case you use the lock in the constructor, which will only ever be executed once per instance, so a non-static lock-object doesn't make any sense here.