[concurrency-interest] jdk9 VarHandle and Fence methods

Peter Levart peter.levart at gmail.com
Wed Sep 16 03:12:10 EDT 2015



On 09/16/2015 03:26 AM, Vitaly Davidovich wrote:
>
> You'd differentiate via whatever protocol is chosen by implementation, 
> i.e. some state that would be set to signal phase changes.  The 
> closest analog is code using CAS, successful or not, to piggyback 
> ordering for surrounding memory ops.
>

You can piggyback ordering of surrounding memory ops if you can reason 
about the phase changes using the state manipulated by CAS even in case 
of a failed CAS if that failure is guaranteed to not be spurious. It's 
the same with lock, but only if the tryLock succeeds. I argue that you 
can not reason about the phase of other thread(s) on the failed tryLock 
even if that is not a spurious failure. A non-spurious tryLock failure 
simply means that some thread has a lock, but does not tell which one.

>   I gave an example upthread where threads compete to get exclusive 
> right to close a socket using tryLock; one thread wins and closes the 
> socket, and losers skip closing the socket but proceed to use memory 
> set inside unlock().  It's a semi contrived example since normally 
> you'd use a CAS for something like this, but it illustrates the gist 
> of what I'm getting at. Of course you can solve these situations using 
> dedicated atomic (or otherwise threadsafe) state, but perhaps one 
> wants to piggyback on existing critical section's fences and not add 
> additional ones.
>

Ah, I see. The following example, right?

On 09/04/2015 05:09 AM, Vitaly Davidovich wrote:
>
> If thread A releases a lock and threads B and C tryLock it, with one 
> succeeding, the failing thread may want to do something else but wants 
> a happens-before edge with the lock release - that's the general use 
> case.  As a simple example, consider two threads tryLock'ing to 
> acquire the exclusive right to close a socket and then perform some 
> additional actions that require ordering of actions done by the 
> releasing thread.  The thread failing to acquire the lock will skip 
> closing the socket but will proceed to do some work that requires 
> happens-before edge.  This is typically done using CAS, with one 
> thread successfully flipping the state, and the others just skip that 
> action that's guarded by the CAS, but can proceed with doing 
> subsequent work.  In other words, one may want to piggyback on the 
> unlock/tryLock to provide the ordering rather than introducing 
> additional dedicated state for this.
>

That's exactly what I'm talking about. B or C failing tryLock doesn't 
mean one of them succeeded (how would any of B or C know that the other 
succeeded if there's no other communication between the two?). It could 
simply mean that both failed because A hasn't released the lock yet. If 
the later is the case, then any relaxed memory operations performed by A 
before releasing the lock can be observed in B or C failing tryLock in 
arbitrary order regardless of whether failed tryLock "guarantees" 
ordering or not, because there hasn't been an unlock in A yet. If those 
operations are not relaxed but follow some release/acquire or SC 
semantics, then they operate by themselves and don't require a failed 
tryLock to guarantee ordering.

Regards, Peter

> sent from my phone
>
> On Sep 15, 2015 4:52 PM, "Peter Levart" <peter.levart at gmail.com 
> <mailto:peter.levart at gmail.com>> wrote:
>
>
>
>     On 09/15/2015 02:56 PM, Vitaly Davidovich wrote:
>>
>>     Hmm, the ordering I had in mind was unlock() happens-before a
>>     failing tryLock.  So a thread failing on tryLock sees operations
>>     preceded by last unlock() as ordered.  This is no different than
>>     successful tryLock or lock() in that regard.
>>
>
>     How can you differentiate between:
>     - unlock() in thread T1 followed by unsuccessful tryLock() in
>     thread T2 and
>     - unsuccessfull tryLock() in T2 followed by unlock() in T1
>
>     You want T1 to already unlock before you observe tryLock() failing
>     in T2 (pressumably because some T3 has already obtained the lock
>     before T2 or because of spurious failure).
>     But T2 failing tryLock() might simply be because T1 hasn't
>     unlocked yet. So regardless of memory effects, you can't reason of
>     ordering in other threads by observing tryLock() failing.
>
>     Do you have an example that proves me wrong?
>
>     Regards, Peter
>
>>     sent from my phone
>>
>>     On Sep 15, 2015 1:16 AM, "Hans Boehm" <boehm at acm.org
>>     <mailto:boehm at acm.org>> wrote:
>>
>>         > How does it slow down lock()?
>>
>>         It depends on the precise guarantee you provide, and I
>>         suspect this thread didn't quite agree on that.  The most
>>         natural one is that the succeeding lock acquisition happens
>>         before the failed trylock().  That implies that if we have
>>
>>         x = 1;
>>         lock();
>>
>>         those can't be reordered by the hardware, since a failing
>>         trylock() would have to see the assignment to x.  That
>>         requires a fence between them on ARM or Power.
>>
>>         I think the right way to think of trylock(), at least
>>         informally, is as allowing spurious failures. I.e. trylock()
>>         is allowed to behave as though the lock was held when it
>>         isn't.  You thus can't conclude anything about other threads
>>         from the fact that it failed.  In this view you don't have to
>>         think about memory ordering issues when reasoning about
>>         correctness, you just reason about spurious failures instead.
>>
>>         If your code is robust against unknown, e.g. debugger,
>>         threads acquiring the lock now and then, then it must be
>>         robust against this sort of spurious failure.  If the lock is
>>         really used only to provide mutual exclusion, this should not
>>         affect correctness.
>>
>>         On Mon, Sep 14, 2015 at 6:41 PM, Vitaly Davidovich
>>         <vitalyd at gmail.com <mailto:vitalyd at gmail.com>> wrote:
>>
>>             How does it slow down lock()?
>>
>>             I don't necessarily disagree but I can certainly see
>>             people considering tryLock to have same ordering effect
>>             as (failed) CAS. It's certainly true that a CAS is a
>>             lower level primitive than a lock, but I don't know if
>>             that resonates immediately when thinking about this. 
>>             It's also the case that on very popular platforms such as
>>             x86 a failing tryLock will have the same ordering as a
>>             successful one, and no difference is observed (and JIT
>>             doesn't do anything different).
>>
>>             I don't understand the debugger thread example - what's
>>             the issue there?
>>
>>             sent from my phone
>>
>>             On Sep 14, 2015 9:07 PM, "Hans Boehm" <boehm at acm.org
>>             <mailto:boehm at acm.org>> wrote:
>>
>>                 FWIW, this general issues is discussed in section 3
>>                 of http://dl.acm.org/citation.cfm?id=1375581.1375591 .
>>
>>                 Yet another argument against providing the stronger
>>                 guarantees is that, on many architectures, it doesn't
>>                 just slow down trylock(), it more importantly slows
>>                 down lock(). In general, if your code cares about
>>                 ordering for unsuccessful trylock(), then it's not
>>                 robust against, say, a debugging thread unexpectedly
>>                 acquiring the lock for a short period.  In my view,
>>                 in such a case, you're no longer using it as a lock,
>>                 and you should be using something else, e.g. an
>>                 atomic object, with stronger guarantees.
>>
>>                 On Fri, Sep 4, 2015 at 4:18 AM, Doug Lea
>>                 <dl at cs.oswego.edu <mailto:dl at cs.oswego.edu>> wrote:
>>
>>                     On 09/03/2015 02:19 PM, Oleksandr Otenko wrote:
>>
>>                         Has anyone come up with the answer about
>>                         ordering for tryLock, or have I missed it?
>>
>>
>>                     You missed the dog not barking :-)
>>
>>                     The Lock specs don't require any specific HB
>>                     effects here on failed
>>                     tryLock. Even if we wanted to, we cannot
>>                     retroactively impose any
>>                     considering that anyone can implement the Lock
>>                     interface (not just j.u.c)
>>                     and some of these might become in violation.
>>
>>                     As you and Vitaly pointed out, there are a few
>>                     fringe cases where
>>                     users might want to impose ordering on failure.
>>                     In jdk9, you'll
>>                     me able to do this with moded VarHandle accesses
>>                     and/or fences. The
>>                     resulting extra fencing might be redundant here
>>                     and there, but if you
>>                     cared enough, you could create and rely on custom
>>                     locks with stronger
>>                     guarantees.
>>
>>                     -Doug
>>
>>
>>                     _______________________________________________
>>                     Concurrency-interest mailing list
>>                     Concurrency-interest at cs.oswego.edu
>>                     <mailto:Concurrency-interest at cs.oswego.edu>
>>                     http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>
>>
>>
>>                 _______________________________________________
>>                 Concurrency-interest mailing list
>>                 Concurrency-interest at cs.oswego.edu
>>                 <mailto:Concurrency-interest at cs.oswego.edu>
>>                 http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>
>>
>>
>>
>>     _______________________________________________
>>     Concurrency-interest mailing list
>>     Concurrency-interest at cs.oswego.edu
>>     <mailto:Concurrency-interest at cs.oswego.edu>
>>     http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20150916/89b44f5a/attachment-0001.html>


More information about the Concurrency-interest mailing list