Do you know if there is guaranteed that synchronized block in java is atomic?
Imagine following case
Thread_1,2:
synchronized(object){object.modify();}
(object is shared variable.)
imagine thread_M will change reference to object like
synchronized(object){object = new Object()}
now imagine threads 1 and 2 are competing over getting the lock on object
Is it possible that following would happened:
1. Thread1: read old object
2. ThreadM: modify object reference & release old object lock
3. Thread2: read new object; check lock; lock on it
4. Thread1: check lock (ok cos old object was read); lock on it
now both threads have a lock and modify same (new) object
So to specify my question - is somewhere guaranteed that in synchronized(object) steps (1 and 4) are atomic (like depicted in step 3)?
Suppose you have some variable, foo
:
Foo foo;
And suppose it holds a reference to an object:
foo = new Foo(...);
And suppose we have a synchronized
block:
synchronized(foo) {
...
}
The synchronized
keywoord does not operate on the variable, foo
, and it does not operate on the statements in the synchronized block.
The only thing that the synchronized
keyword does here is it prevents other threads from synchronizing on the same instance at the same time.
If you reassign the variable, foo
to refer to some different instance while thread A is inside the block, then some other thread B will be able to enter the same block at the same time because each of the two threads will be synchronized on a different instance.
You can reassign object
while you are synchronized on object
, but I can't think of a scenario where reassigning a field used for locking is a good idea.
No other thread will be able to acquire the lock on the old value of object
until thread M exits its synchronized block, but another thread will be able to acquire a lock on the new object as soon as it is visible to that thread.
Modifications made by a thread before releasing a lock are guaranteed to be visible to threads that acquire the lock afterwards. But since you are reassigning the lock itself, the acquiring thread may not see that it has been changed, and acquire a lock on the old value. Then they would still not see that object
has been reassigned.
Declaring object
as a volatile
variable would ensure that its "current" value is used for locking. But it wouldn't prevent two threads from modifying the same instance concurrently:
To avoid all of this, just create a separate object for locking, and never change it.
You are synchronizing over the object that that "object" points to, not the variable holding the value.
However, because both pieces of code synchronize on your object before moving forward, you're safe -- although this is a poor design pattern.
You may find less confusion if you use synchronized methods instead of synchronized code blocks.
Also, just my opinion, but synchronized(object) seems like a VERY poor design pattern. That's just my opinion, but I never do something like that.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.