Reputation: 139
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?
Upvotes: 3
Views: 278
Reputation: 31417
You have created 3 thread and started, so, I hope you would be aware that execution of thread are not guarantee immediately. It might be possible that, thread which you created and started may start running at the end, which is in your case happening. But, that is not always guarantee. For example, same code I have executed and it is giving expected output on Ideone
Thread Id 8, expected value is 5, value=5
Thread Id 9, expected value is 10, value=10
Thread Id 10, expected value is 15, value=15
But, if you wanted to execute thread one after another, then you might look join method.
Upvotes: 2
Reputation: 8758
There is no unpredictable results here. And synchronization works correctly. The thing is that you call method setValue()
and then after some time you call getValue()
. In your example threads overlay in such manner that value 15 is set after other threads call setValue()
but before any of them call getValue()
.
You can add Thread.sleep(1000)
in the run()
method of third thread and see that results may change.
Synchronized method acquire explicit lock on object but only for duration of that method. Once method is finished lock is returned and other threads are free to take it.
Upvotes: 5