When an object needs to be synchronized, the IDE complains if it's not set non-final (because its reference isn't persistent):
private static Object myTable;
....
synchronized(myTable){ //IDE complains!
//access myTable here...
}
We all know the IDE complains to prevent another thread from entering the guarded block if the thread holding the lock changes the non-final object's references.
But could a synchronized object's reference also be changed by another thread B while thread A holds the lock for the same object?
Yes, it can. All non-final variables/fields can change their values/references to an object at any time, whether an object is inside or outside a guarded block. Therefore you always need to use a third party lock in combination with non-final fields:
Only setting a field as final would prevent any reference changements from either inside or outside the lock. One could say that the latter is an errorful Java behaviour and references should be locked as well by calling synchronized. But that's the way it needs to be, otherwise the code would become unmaintainable.
Well, at least some new kind of field like
private guardable Object o;
would be needed for that purpose. ;)EDIT:
Here's a test case within a class Test (note that constructors load threads quite unpredictable, so therefore the wait(1000)...but that's only meant to be a test, usually you shouldn't start threads in constructors at all):
The results are:
You can see on line 5 that there is no prevention of the reference changement by the lock. Then the test case was changed to:
Yielding this result:
Here the second thread waits for acquiring the LOCK, and that's exactly what we wanted.
If you mean "could another thread change the value of the
myTable
variable, the answer is "absolutely"... assuming there's a code path that would allow that. It's a private variable, so you should be able to find all the code that can change the value.Holding a lock just stops another thread from acquiring the same lock. It doesn't have any effect on what code can access which variables, in itself.
As a side-note, it's important to differentiate between an object, a variable, and the value of the variable (which is a reference, not an object). So there's no such thing as a "final object" - only variables (and classes and methods) can be final. Likewise there's no such thing as a "synchronized object", and you can't change an "object's reference" - you can change the value of a variable so that it's a reference to a different object. Making these distinctions clear in your mind may help you when thinking about what's going on here.