[concurrency-interest] park and unpark low-level details

Andrew Haley aph at redhat.com
Fri Nov 20 13:41:48 EST 2009


Dave Dice wrote:
> On 2009-11-20, at 12:46 PM, Andrew Haley wrote:
>
>> Something I've been wondering about.
>>
>> In "The java.util.concurrent Synchronizer Framework" Doug writes:
>>
>> << This simple mechanism is similar to those used, at some level, in
>> the Solaris-9 thread library [11], in WIN32 "consumable events", and
>> in the Linux NPTL thread library, and so maps efficiently to each of
>> these on the most common platforms Java runs on.  (However, the
>> current Sun Hotspot JVM reference implementation on Solaris and Linux
>> actually uses a pthread condvar in order to fit into the existing
>> runtime design.) >>
>>
>> What do you man by this?  I guess there's a nice way to map park and
>> unpark onto low-level NPTL primitives (futexes, perhaps?)  Did you
>> have a sketch of a design for that?
>

> We preferred to use more standardized interfaces.  I experimented
> with using futexes instead of the usual condvar-mutex-flag tuple but
> it wasn't particularly better.

I'm not surprised.  I did some profiling, and even with quite heavily
contended locks the time spent in park and unpark is often down in
the noise.  Amazing, really.  :-)

> (Likewise, Solaris has low-level __lwp_park and __lwp_park
> interfaces that also work nicely, but they aren't officially exposed
> and subject change from release to release).

> One of the more interesting approaches is to use pipe pairs.  (I
> left comments in the code that explain this in more detail).
> Perversely, this is one of the best implementations for Solaris and
> Linux, except that it can consume excessive number of file
> descriptors, which is why we're not using it.

Yes, I read that.  I guess you'd use open() with O_NONBLOCK and
select() with a timeout for timed waits.  This does have a really nice
feel to it; it's a shame file descriptors turn out to be such a scarce
resource.

>> It probably doesn't much matter, given that pthread mutex and conndvar
>> signal a fairly thin wrappers over futexes, but unparking a blocked
>> thread requires three pthread_ calls:
>>
>>     int status = pthread_mutex_lock(_mutex);
>>
>>     AnyWaiters = _nParked ;
>>
>>     status = pthread_mutex_unlock(_mutex);
>>
>>     if (AnyWaiters != 0) {
>>        status = pthread_cond_signal(_cond);
>>     }
>

> You're apparently looking at the PlatformEvent:: implementation and
> not Parker::.  PlatformEvent:: is used by the built-in
> synchronization primitives and native C++ JVM internal mutexes and
> monitors, whereas Parker:: is infrastructure used by LockSupport.
> They're similar -- and someday should be reconciled -- but have
> slightly different semantics.

Ah, my mistake.  However, exactly the same is true of Parker::park:

  status = pthread_mutex_lock(_mutex);
  s = _counter;
  _counter = 1;
  if (s < 1) {
        status = pthread_mutex_unlock(_mutex);
        status = pthread_cond_signal (_cond) ;
     }
  } else {
    pthread_mutex_unlock(_mutex);
  }

I suppose this question is more to do with the fact that it doesn't
quite feel right (to me) to be using all these pthread calls in the
lowest-level Java primitives, rather than anything real to do with
performance.

Thanks,
Andrew.



More information about the Concurrency-interest mailing list