[concurrency-interest] Unsynchronized lazy conditions

Alex Otenko oleksandr.otenko at gmail.com
Thu May 31 05:58:24 EDT 2018


The original requirement was it’s ok to sometimes log Warning several times. All this hacky atomicity is unnecessary. Just declare private volatile boolean warned, and leave the rest of the code as is.

Alex

> On 31 May 2018, at 10:22, Viktor Klang via Concurrency-interest <concurrency-interest at cs.oswego.edu> wrote:
> 
> 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 <mailto: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 <mailto:Concurrency-interest at cs.oswego.edu>
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest <http://cs.oswego.edu/mailman/listinfo/concurrency-interest>
> 
> 
> 
> 
> -- 
> Cheers,
>> _______________________________________________
> Concurrency-interest mailing list
> 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/20180531/9833ad95/attachment.html>


More information about the Concurrency-interest mailing list