Trying to visualize and understand synchronization.
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.
A synchronized block of code can only be executed by one thread at a time. Synchronization in Java is basically an implementation of monitors . When synchronizing a non static method, the monitor belongs to the instance. When synchronizing on a static method , the monitor belongs to the class.
In simple words a static synchronized method will lock the class instead of the object, and it will lock the class because the keyword static means: "class instead of instance". The keyword synchronized means that only one thread can access the method at a time.
If a thread wants to execute a static synchronized method, then thread requires a class level lock. Once a thread got the class level lock, then it is allowed to execute any static synchronized method of that class. Once method execution completes automatically thread releases the lock.
The difference is simple: if the locked-on object is in a static
field, then all instances of MyClass*
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With