[concurrency-interest] Unsynchronized lazy conditions

Viktor Klang viktor.klang at gmail.com
Thu May 31 05:22:28 EDT 2018


Aleksey's suggestion(s) is/are definitely cleaner than mine:

Depending on performance requirements the following might be cheaper,
of course assuming you can type-wise hide the AtomicBoolean inheritance
from consumer code:

class Foo extends AtomicBoolean { // No indirection due to the allocation
of AtomicBoolean
   public void run() {
     if (!get() && !getAndSet(true)) { // LOCK XCHG instead of LOCK CMPXCHG
       LOG.warn("Warning");
     }
   }
}

On Thu, May 31, 2018 at 9:51 AM, Aleksey Shipilev via Concurrency-interest <
concurrency-interest at cs.oswego.edu> wrote:

> On 05/31/2018 07:07 AM, Shevek via Concurrency-interest wrote:
> > Hi,
> >
> > I'd like to issue a warning message a relatively low number of times in
> a multi-threaded
> > application. My code is this:
> >
> > class Foo {
> >   private boolean warned;
> >
> >   public void run() {
> >     if (!warned) {
> >        LOG.warn("Warning");
> >        warned = true;
> >     }
> >   }
> > }
> >
> > This is the only access to the variable 'warned', the value change is
> deliberately unsynchronized,
> > and monotonic. Am I right to believe that:
> >
> > * The first call WILL issue a warning.
>
> Yes.
>
> > * Any thread will issue the warning AT MOST once.
>
> Yes, I think so. It encroaches on darker corners of JMM, but it still does
> what you want, methinks.
>
> > * Some (later) threads may not issue the warning, if the updated value
> is flushed to the heap and
> > they load it?
>
> Yes, except that "flushed to heap" part: that one is an implementation
> detail.
>
>
> > Is there a better way to do this without sacrificing performance? Is
> this what the mysterious
> > AtomicBoolean.lazySet, or even weakCompareAndSet is about?
>
> The classic way to do this is to do test and test-and-set:
>
> class Foo {
>    private final AtomicBoolean warned;
>
>    public void run() {
>      if (!warned.get() && warned.compareAndSet(false, true)) {
>        LOG.warn("Warning");
>      }
>    }
> }
>
> This gives you global only-once property, without sacrificing performance.
>
> There are options how do you represent "warned". I'd start with
> AtomicBoolean, and then switched to
> AtomicIntegerFieldUpdater over volatile field, or VarHandle if footprint
> became a problem. With
> VarHandles, you can even mix the modes: make the first "test" in plain
> mode, and then do the CAS, if
> first volatile check is too costly. But all of this is red herring until
> there is a pressing need.
> One-off guards are doable with just AtomicBoolean.
>
> -Aleksey
>
>
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
>


-- 
Cheers,
√
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20180531/f29ab400/attachment.html>


More information about the Concurrency-interest mailing list