See this answer. It says:
Six really bad examples;
...
locking on a mutable field. e.g. synchronized(object) { object = ...; }
What's wrong with locking on a mutable field? What if object
was declared as final
but was not an immutable class?
It is a bad idea because if another thread changes the reference in the critical section, the threads will no longer see the same reference, and so they will not synchronize on the same object, thus running uncontrolled. Example:
synchronized(lock1) {
lock1 = new Object();
sharedVariable++;
}
Assume 2 threads are trying to enter this critical section. Thread 1 enters and thread 2 waits. Thread 1 goes in, reassigns lock1
and proceeds. Now thread 2 sees a different lock than what thread 1 acquired, which is also free, so it can also enter the critical section. Fun ensues!
If the object is final
, you cannot reassign the reference to a different object, so the above problem no longer applies.
"Mutable" isn't the right word here. It's okay to lock on a mutable object, i.e. an object with state. What's wrong is to lock on a field, change it, and expect another thread to lock on the same object.
I don't think locking a mutable object is bad in itself. It is just very hard to get it right. There are other models for concurrent processing, like actors. I suggest you look into Akka, which can be used from both Java and Scala, and is a very solid implementation.