If I synchronized two methods on the same class, can they run simultaneously?
If I synchronized two methods on the same class, can they run simultaneously on the same object? For example:
class A {
public synchronized void methodA() {
//method A
}
public synchronized void methodB() {
// method B
}
}
I know that I can't run methodA()
twice on same object in two different threads. same thing in methodB()
.
But can I run methodB()
on different thread while methodA()
is still running? (same object)
Solution 1:
Both methods lock the same monitor. Therefore, you can't simultaneously execute them on the same object from different threads (one of the two methods will block until the other is finished).
Solution 2:
In the example methodA and methodB are instance methods (as opposed to static methods). Putting synchronized
on an instance method means that the thread has to acquire the lock (the "intrinsic lock") on the object instance that the method is called on before the thread can start executing any code in that method.
If you have two different instance methods marked synchronized and different threads are calling those methods concurrently on the same object, those threads will be contending for the same lock. Once one thread gets the lock all other threads are shut out of all synchronized instance methods on that object.
In order for the two methods to run concurrently they would have to use different locks, like this:
class A {
private final Object lockA = new Object();
private final Object lockB = new Object();
public void methodA() {
synchronized(lockA) {
//method A
}
}
public void methodB() {
synchronized(lockB) {
//method B
}
}
}
where the synchronized block syntax allows specifying a specific object that the executing thread needs to acquire the intrinsic lock on in order to enter the block.
The important thing to understand is that even though we are putting a "synchronized" keyword on individual methods, the core concept is the intrinsic lock behind the scenes.
Here is how the Java tutorial describes the relationship:
Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. (The API specification often refers to this entity simply as a "monitor.") Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state and establishing happens-before relationships that are essential to visibility.
Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them. A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock. As long as a thread owns an intrinsic lock, no other thread can acquire the same lock. The other thread will block when it attempts to acquire the lock.
The purpose of locking is to protect shared data. You would use separate locks as shown in the example code above only if each lock protected different data members.