[ImageJ-devel] [fiji-devel] Lock-free bit fields, was Re: What's left to do for ImgLib2

Stephan Saalfeld saalfelds at janelia.hhmi.org
Thu Oct 30 10:18:11 CDT 2014


Thanks for the articles!

I have more comments on the matter.  In fact, all types have the same
problem.  Even for a non-native ComplexType read and write would not be
atomic and thus not thread-safe.  The problem is that, for non-native
types, it is sufficient for multi-threaded code to synchronize on the
type instance itself.  For native types (e.g. ComplexDoubleType) and for
other proxy mechanisms such as Composites or ReadWriteConverters, this
doesn't work.  How about a getLock() (or getMonitor()) method as part of
Type whose purpose is to return a lock that enables synchronization on
that particular's type content.  Should that lock be constant for a
type's lifetime?  Proxy types for which access is atomic could return
themselves, just as Types that actually contain their content.

I like Tobias' proposal with a Hash of locks for NativeTypes, something
similar is necessary for other writable proxies.

Best,
Stephan



On Thu, 2014-10-30 at 14:51 +0100, Adrian Daerr wrote:
> Hi,
> 
> >> By lock-free I mean setting the value and then checking whether the
> >> value is actually what was expected (and if not, retry).
> >
> > A naïve implementation of this technique could easily result in a very
> > nasty ping-pong effect: if one thread tries to clear a bit and the next
> > thread tries to set it, it is very to run into a trap when not leaving a
> > way for one thread to win.
> >
> > The safest way to resolve this issue is to reinstate the lock-on-write
> > method that was in place earlier
> [..]
> >
> > An alternative might be to give up lock-freedom in favor of wait-freedom
> > [*2*]. In this regard, a more performant version might be
> [..]
> > to use Optimistic Concurrency Control [*3*]:
> 
> > 	final long original = dataAccess.getValue(i1);
> > 	if ( value ) {
> > 		final long newValue = original | (1l << shift);
> > 		dataAccess.setValue(i1, newValue);
> > 		if ( newValue != dataAccess.getValue( i1 ) ) {
> > 			synchronized (dataAccess) {
> > 				dataAccess.setValue( i1, dataAccess.getValue(i1) | (1l << shift) );
> > 			}
> > 		}
> > 	}
> [snip]
> 
> Hum, I do not if this is really a comparable situation, but it looks a 
> lot like the double-checked locking (DCL) idiom, which is broken [1].
> 
> FWIW,
> cheers and good luck,
> Adrian
> 
> 
> [1]
> TL;DR : You cannot have as-if-serial semantics across threads unless you 
> use synchronized.
> 
> "Double-checked locking: Clever, but broken
> Do you know what synchronized really means?" By Brian Goetz
> http://www.javaworld.com/article/2074979/java-concurrency/double-checked-locking--clever--but-broken.html
> 
> and its follow-up article
> 
> "Can double-checked locking be fixed?
> No matter how you rig it, double-checked locking still fails" (also by 
> Brian Goetz)
> http://www.javaworld.com/article/2075306/java-concurrency/can-double-checked-locking-be-fixed-.html




More information about the ImageJ-devel mailing list