Spurious LockSupport.park() return?

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Spurious LockSupport.park() return?

Millies, Sebastian

Hello there,

 

in the recent discussion about  unpark/park memory visibility, it was explained why LockSupport.park() is allowed to return spuriously.

It hasn’t become clear to me if that’s just semantics (we can’t forbid it), or whether it’s a real problem.

 

I am just now dealing with someone else’s code that behaves strangely, and the strangeness may be explained by park() returning

spuriously. My question is: Is that a hypothesis to be taken seriously, or is spurious unparking not a practical possibility?

 

FWIW: the structure of the code is like this:

 

Threads A and B:

 

for (;;) {

  LockSupport.park();

  synchronized (monitor) {

    if (mayRun) {

      queuedThreads.remove(); // remove this from the queue (**)

      mayRun = reconsider();

      break;

    }

    // otherwise park again and stay at the head of the queue

  }

}

 

Thread C:

LockSupport.unpark(queuedThreads.peek())

 

if A, B are in the queue, C wakes up A which is should remove itself from the queue (and later unpark B, etc.) However, if B is also unparked (spontaneously and at ca. the same time) and races ahead of A to remove A from the head of the queue and set mayRun to false, then A may never be unparked again, because it’s no longer in the queue.

 

Clearly, the line (**) is buggy because it does not check the assumptions that are made in the comments. But I find this scenario far-fetched. Could it really happen?

 

 

 

Sebastian Millies

PPM, Saarbrücken C1.67, +49 681 210 3221

 


Software AG – Sitz/Registered office: Uhlandstraße 12, 64297 Darmstadt, Germany – Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Eric Duffaut, Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Spurious LockSupport.park() return?

Justin Sampson
Sebastian Millies wrote:

> in the recent discussion about  unpark/park memory visibility, it
> was explained why LockSupport.park() is allowed to return
> spuriously. It hasn't become clear to me if that's just semantics
> (we can't forbid it), or whether it's a real problem.

There are lots of reasons that park() can appear to return
"spuriously," having to do with the timing of park and unpark. There
can be left-over unparks from earlier synchronization operations,
for example, which has to be allowed in order to implement locking
correctly (it's better to have too many unparks than too few!).
There can also be races between park() and unpark() themselves, in
which case park() errs on the side of returning spuriously rather
than risk missing an unpark().

> Clearly, the line (**) is buggy because it does not check the
> assumptions that are made in the comments. But I find this
> scenario far-fetched. Could it really happen?

If the code is buggy, it has to be fixed. :) It seems weird to be
using park/unpark in conjunction with a synchronized block. Why not
use higher-level concurrency utilities?

Cheers,
Justin

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Spurious LockSupport.park() return?

David M. Lloyd-3
In reply to this post by Millies, Sebastian
Yes, you should always treat spurious return as a real possibility.
It's not the implementation of park necessarily (though it may be that
as well), so much as the fact that anyone can call unpark() on a thread
for a wide variety of reasons, including there being a "leftover"
unpark() "permit" from some previous user.

On 01/21/2015 01:25 PM, Millies, Sebastian wrote:

> Hello there,
>
> in the recent discussion about  unpark/park memory visibility, it was
> explained why LockSupport.park() is allowed to return spuriously.
>
> It hasn’t become clear to me if that’s just semantics (we can’t forbid
> it), or whether it’s a real problem.
>
> I am just now dealing with someone else’s code that behaves strangely,
> and the strangeness may be explained by park() returning
>
> spuriously. My question is: Is that a hypothesis to be taken seriously,
> or is spurious unparking not a practical possibility?
>
> FWIW: the structure of the code is like this:
>
> Threads A and B:
>
> for (;;) {
>
>    LockSupport.park();
>
>    synchronized (monitor) {
>
>      if (mayRun) {
>
>        queuedThreads.remove(); // remove this from the queue (**)
>
>        mayRun = reconsider();
>
>        break;
>
>      }
>
>      // otherwise park again and stay at the head of the queue
>
>    }
>
> }
>
> Thread C:
>
> LockSupport.unpark(queuedThreads.peek())
>
> if A, B are in the queue, C wakes up A which is should remove itself
> from the queue (and later unpark B, etc.) However, if B is also unparked
> (spontaneously and at ca. the same time) and races ahead of A to remove
> A from the head of the queue and set mayRun to false, then A may never
> be unparked again, because it’s no longer in the queue.
>
> Clearly, the line (**) is buggy because it does not check the
> assumptions that are made in the comments. But I find this scenario
> far-fetched. Could it really happen?
>
> *Sebastian Milli**es*
>
> PPM, Saarbrücken C1.67, +49 681 210 3221
>
>
> Software AG – Sitz/Registered office: Uhlandstraße 12, 64297 Darmstadt,
> Germany – Registergericht/Commercial register: Darmstadt HRB 1562 -
> Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman),
> Eric Duffaut, Dr. Wolfram Jost, Arnd Zinnhardt; -
> Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas
> Bereczky - *http://www.softwareag.com*
>
>
>
> _______________________________________________
> Concurrency-interest mailing list
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>

--
- DML
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Spurious LockSupport.park() return?

oleksandr otenko
Not necessarily even a leftover unpark from previous user. It can be
your own.

Here's why.

You can't do all of these atomically:

tell who to wake up (ie add yourself to wait list)
check condition does not hold yet
park()

I mean, of course, you could wrap the first two steps in synchronized,
but then you don't get anything new on top of wait(), so we suppose we
aren't using synchronized for some reason.

If you check condition, then tell who to wake up, then you can miss an
unpark. If you tell who to wake up, then check the condition, then you
can get a spare unpark.

Alex

On 21/01/2015 19:58, David M. Lloyd wrote:

> Yes, you should always treat spurious return as a real possibility.
> It's not the implementation of park necessarily (though it may be that
> as well), so much as the fact that anyone can call unpark() on a
> thread for a wide variety of reasons, including there being a
> "leftover" unpark() "permit" from some previous user.
>
> On 01/21/2015 01:25 PM, Millies, Sebastian wrote:
>> Hello there,
>>
>> in the recent discussion about  unpark/park memory visibility, it was
>> explained why LockSupport.park() is allowed to return spuriously.
>>
>> It hasn’t become clear to me if that’s just semantics (we can’t forbid
>> it), or whether it’s a real problem.
>>
>> I am just now dealing with someone else’s code that behaves strangely,
>> and the strangeness may be explained by park() returning
>>
>> spuriously. My question is: Is that a hypothesis to be taken seriously,
>> or is spurious unparking not a practical possibility?
>>
>> FWIW: the structure of the code is like this:
>>
>> Threads A and B:
>>
>> for (;;) {
>>
>>    LockSupport.park();
>>
>>    synchronized (monitor) {
>>
>>      if (mayRun) {
>>
>>        queuedThreads.remove(); // remove this from the queue (**)
>>
>>        mayRun = reconsider();
>>
>>        break;
>>
>>      }
>>
>>      // otherwise park again and stay at the head of the queue
>>
>>    }
>>
>> }
>>
>> Thread C:
>>
>> LockSupport.unpark(queuedThreads.peek())
>>
>> if A, B are in the queue, C wakes up A which is should remove itself
>> from the queue (and later unpark B, etc.) However, if B is also unparked
>> (spontaneously and at ca. the same time) and races ahead of A to remove
>> A from the head of the queue and set mayRun to false, then A may never
>> be unparked again, because it’s no longer in the queue.
>>
>> Clearly, the line (**) is buggy because it does not check the
>> assumptions that are made in the comments. But I find this scenario
>> far-fetched. Could it really happen?
>>
>> *Sebastian Milli**es*
>>
>> PPM, Saarbrücken C1.67, +49 681 210 3221
>>
>>
>> Software AG – Sitz/Registered office: Uhlandstraße 12, 64297 Darmstadt,
>> Germany – Registergericht/Commercial register: Darmstadt HRB 1562 -
>> Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman),
>> Eric Duffaut, Dr. Wolfram Jost, Arnd Zinnhardt; -
>> Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas
>> Bereczky - *http://www.softwareag.com*
>>
>>
>>
>> _______________________________________________
>> Concurrency-interest mailing list
>> [hidden email]
>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>
>

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest