I'm having a hard time to understand how synchronized works on two distinct methods from same object. I have a class, with two instance methods that are declared synchronized. Three threads access this object's two synchronized methods, but the result is unexpected. The threads interchangeably access the two methods. They don't wait for the lock of the entire object to be released. Here is the sample:
public class ThreadSafeCounterSameMonitor2 {
private int value;
public synchronized int getValue() {
return this.value;
}
public synchronized void setValue(int value) {
this.value = value;
}
public static void main(String[] args) {
ThreadSafeCounterSameMonitor2 nts = new ThreadSafeCounterSameMonitor2();
Thread th1 = new Thread(new Runnable() {
public void run() {
nts.setValue(5);
System.out.println("Thread Id " + Thread.currentThread().getId() + ", expected value is 5, value=" + nts.getValue());
}
});
Thread th2 = new Thread(new Runnable() {
public void run() {
nts.setValue(10);
System.out.println("Thread Id " + Thread.currentThread().getId() + ", expected value is 10, value="
+ nts.getValue());
}
});
Thread th3 = new Thread(new Runnable() {
public void run() {
nts.setValue(15);
System.out.println("Thread Id " + Thread.currentThread().getId() + ", expected value is 15, value="
+ nts.getValue());
}
});
th1.start();
th2.start();
th3.start();
}
}
The result I am getting is surprising:
Thread Id 13, expected value is 15, value=15.
Thread Id 12, expected value is 10, value=15.
Thread Id 11, expected value is 5, value=15.
So, where I was expecting 10, it gets 15. Where I was expecting 5 it still gets 15.
My understanding was that all synchronized methods from the monitor will get locked when accessed by a thread. But they are not. In the same run() method of a thread, I set one value, then retrieve it and it gives me another value, changed from another thread.
I have often read something like "A synchronized method acquires an implicit lock on the this reference", but this is clearly not true, not even for all methods synchronized methods in the same monitor. Or am I doing something bad in the code?
My question is, how can I really lock the whole object's synchronized methods? Do you know a tutorial that explains well this concept?