[concurrency-interest]RE: RE :RE: JSR 166 draft API (David Holmes)

Eric D Crahen crahen@cse.Buffalo.EDU
Wed, 7 Aug 2002 21:57:23 -0400 (EDT)

Hi Dave,

Thanks for the quick response.

I didn't realize the difference in the clearThreadLocals() & remove()
methods. Thanks for pointing that out.

> Often when using a barrier, after the barrier has been tripped you need
> to do some special processing. Only one thread needs to do that
> processing but all threads are executing the same piece of code. By
> returning the index you allow threads to discriminate in their actions.

To do this right, wouldn't each thread need to know its identity when
going in? I'm just thinking that a task may want to pick up doing the
same thing it was doing when it went in, and if they don't know thier
number going in (or can't assign thier own), coming they might take the
wrong paths and end up switching some context information that may be
stored in thread locals.

It might depend on how you use the Barrier I guess. What I would tend to
do is give two different task objects a reference to the barrier to wait
on if thier chores were different.

> You can then arbitrarily pick a thread to execute the once-only action
> based on its index.

Isn't there a Runnable that can be associated in one of the constructors
for this?

> Things that share a common interface should in some way be
> interchangable (not completely arbitrarily of course, but there should
> be some degree of interchangability). Locks and Read/write locks and
> semaphores have that property - conditions and barriers do not. They are
> so different in functionality that having a common interface would, I
> think, be misleading.

It seems like it could be useful to return Waitable objects (tokens to
wait for values to be calculateed, or for conditions to occur, or other
things), or to build of queue of things that need waiting.
It doesn't seem any less interchangeable than semaphores and recursive
locks, though. They really only share the general usage protocol, and that
seems to be what that Lock interface really reflect best. I think a
Waitable does the same for blocking operations. I do understand your
point of view, though.

> Most of the variants of executors reduce to a threadpool with some
> specific properties - the properties fully controllable by the
> Intercepts class. The pendulum has swung from having separate classes
> through to having a single implementation class and some factory
> methods, but may be swinging back again. Feedback like this may help
> push that pendulum :)

I'll try to finish the revision I was supposed to be making this week on
that pattern, maybe it will be helpful :)

> Mutex was a non-reentrant lock class. The current thinking is that
> having a non-reentrant lock class is needed so very rarely that it is
> not worth having. A distinction is being made between needing a
> non-reentrant lock versus never exercising the reentrancy portion of a
> reentrant lock ie. would your code be broken if a reentrant lock was
> used instead? The general answer is no because the only difference
> between a non-reentrant lock and a re-entrant lock that is only used
> non-reentrantly, is in the erroneous circumstance where you do in fact
> attempt to use the lock reentrantly.

I hadn't thought about it like that; I just was instinctively reaching for
a Mutex. I work with other languages as well, and the first things I
usually look for are the threads & mutexes. What you are saying is
probably simpler.

> Of course, there are many that argue that locks should be non-reentrant
> only and that any situation that needs a reentrant lock reflects a
> broken design. Such people tend to program in C not an OO language. In
> concurrent OO languages reentrancy makes live a lot simpler - it's not
> essential but it makes things simpler.

I'm an OO programmer, but I think there are alot of times that using
non-recursive locks can be helpful in ironing out an cleaner design. Its
not always the case that recursive locks make bad designs, but sometimes
its a good hint that something should be refactored. That's just my
experience though. If the performance is the same for recursive
and non-recursive Locks, then it might be enough to just include
the recursive one.

> Adjective based interface names like Comparable, Sortable, Cloneable,
> Lockable to me imply a property of the object: it can be compared, it
> can be sorted, it can be cloned etc.
> Noun based interface names like Lock, Map, List tell me that an object
> *is* something. I use this object as a Map, as a List, as a Lock etc.

This is the same logic I was using except that I looked at it as a thing
that can be locked, rather then as a Lock. Its usually called Lockable in
Doug Schmitts (probably spelled that wrong) papers; thats where I first
began reading about concurrency patterns and might be why I'm looking that

- Eric