[concurrency-interest] Re: synchronized vs ReentrantLock semantic

Dawid Kurzyniec dawidk at mathcs.emory.edu
Mon Jun 13 18:28:29 EDT 2005


Gregg Wonderly wrote:

>
>
> Michael Smith wrote:
>
>> Since this seems like the fundamental use-case for this API, we can 
>> only assume that we are blind and just aren't seeing something in the 
>> code.  Can someone provide more details about how and where thread 
>> memory and main memory are synchronized when using 
>> ReentrantReadWriteLock's locks?
>
>
> When you use this lock to protect reading and writing of other values, 
> those values must be volatile if you want their changed state to 
> propagate between threads/processors etc.
>
Gregg,

I am not sure if you're right on this (I hope you aren't), since it 
would indirectly imply that all shared state protected by 
java.util.concurrent.locks.* need to be volatile, including all the 
fields of shared objects deep in the graph. This conclusion follows from 
the fact that in the ReentrantReadWriteLock, the same synchronizer 
instance is used by the write lock and the read lock. Either of the 
following must be true: 1) the synchronizer ensures visibility by 
flushing caches, or 2) it does not. If 2) is true, it is also true for 
all other locks based on AbstractQueuedSynchronizer, in particular for 
the ReentrantLock. This would necessitate making all the shared state 
volatile when protecting it by ReentrantLock. But it is not done in 
internal j.u.c. classes, e.g. LinkedBlockingQueue. It seems that the 
only logical conclusion is that AbstractQueuedSynchronizer does provide 
visibility semantics, although I agree with Michael Smith that it does 
not follow from the javadoc at all.

 I think that a scenario that you had in mind is synchronized write and 
lock-free volatile read, kind of like the "volatile read / synchronized 
write" pattern that I inquired about a few e-mails back.

It seems that the original question posed by Michael Smith has not yet 
been answered; let me reformulate it and ask again:

We all know that the AbstractQueuedSynchronizer provides atomicity. But 
does it also ensure visibility?

(The contract of monitorExit ensures visibility, so I would expect the 
answer to be yes based on the Lock javadoc, but it does not follow from 
the AbstractQueuedSynchronizer javadoc, or the source code, as far as I 
can see).


In particular, is it safe to replace:

synchronized (x) {
   ...
}

by:

lock.lock();
try {
   ...
}
finally {
   lock.unlock();
}


regardless of what the "..." is?

Regards,
Dawid




More information about the Concurrency-interest mailing list