[cpp-threads] High-level concurrency issues

Boehm, Hans hans.boehm at hp.com
Tue Oct 18 00:18:59 BST 2005


> > 
> > I agree that typical developers must never need to know about the 
> > memory model. (Makes me think of Jack Nicholson's character saying: 
> > "The truth? You can't handle the truth.")
> > 
> > But if you mean that 'doing the right locking' is the 
> answer, I would 
> > disagree with that because locks are known to be inherently 
> > inappropriate for building modern software -- they aren't 
> composable.
> 
> FWIW, that's what rang the biggest alert bell to me, too.
> 
Somewhat playing devil's advocate here, could someone make that
statement about "not composable" precise?  I've certainly seen it
before, but I think it would help to understand exactly what we're
talking about here.

My general model of how when you acquire locks is:

1) Classes are designed to be thread-safe in the SGI STL sense:  It is
the clients responsibility to ensure that a (logical) write access never
occurs concurrently with another access to the object.  If two
concurrent (logical) read accesses to the object require a write behind
the scenes (e.g. to update a cache), then it is the objects
responsibility to provide locking for sufficient mutual exclusion behind
the scenes.  Effectively objects I construct are thread-safe in the same
sense that primitive integers are thread-safe in pthreads.

2) If I write client code that may write to an object and make another
access to the same object, I must ensure that those accesses cannot take
place concurrently, e.g. by acquiring a lock around them.

3) If I need to ensure atomicity of a sequence of operations with
respect to some other operations, I presumably already need to acquire a
lock by rule (2), and I then need to avoid releasing the lock between
operations.

This can get me into trouble if atomicity or other considerations
require me to hold a lock during a client call-back, for example.  But
in most cases, it seems to work tolerably well, and layers of calls seem
to compose reasonably.  And I'm not 100% convinced that the cases in
which it breaks don't have single-threaded lock-free analogs in which I
break object invariants with an unintentional recursive call.

(Transactional memory might be better, but we're not ready to
standardize that, I think.)

This does not mesh at all well with a model in which all locking is done
on entry to member function, and locks the object itself.  But I've
stated previously that I don't like that model.  And I don't claim I
know how to program with it.  

Hans



More information about the cpp-threads mailing list