[concurrency-interest] Unsynchronized lazy conditions

Valentin Kovalenko valentin.male.kovalenko at gmail.com
Fri Jun 1 13:45:08 EDT 2018


Peter, and now you have contention on logExec.submit. Not to mention that
logging frameworks like already provide asynchronous logging and Log4J2,
for example, uses Disruptor (
https://logging.apache.org/log4j/2.x/manual/async.html), which passes
messages between threads faster than any bounded queue you will use in
Executor.submit.

> Peter <
> Logging can cause
> significant contention, expecially under stress, so you don't want to be
> logging unnecessarily.
>
> You know what the best solution was?  A single threaded Executor.  No
> more contention due to logging.
>
> static void log(Level level, String message, Object[] parameters,
> Throwable thrown){
>          final LogRecord record = new LogRecord(level, message);
>          record.setParameters(parameters);
>          record.setThrown(thrown);
>      logExec.submit(new Runnable(){
>          public void run() {
>          logger.log(record);
>          }
>      });
>      }

Regards,
Valentin
[image: LinkedIn] <https://www.linkedin.com/in/stIncMale>   [image: GitHub]
<https://github.com/stIncMale>   [image: YouTube]
<https://www.youtube.com/user/stIncMale>

On 1 June 2018 at 10:00, <concurrency-interest-request at cs.oswego.edu> wrote:

> Send Concurrency-interest mailing list submissions to
>         concurrency-interest at cs.oswego.edu
>
> To subscribe or unsubscribe via the World Wide Web, visit
>         http://cs.oswego.edu/mailman/listinfo/concurrency-interest
> or, via email, send a message with subject or body 'help' to
>         concurrency-interest-request at cs.oswego.edu
>
> You can reach the person managing the list at
>         concurrency-interest-owner at cs.oswego.edu
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of Concurrency-interest digest..."
>
>
> Today's Topics:
>
>    1. Re: Unsynchronized lazy conditions (Alex Otenko)
>    2. Re: Unsynchronized lazy conditions (Peter)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Fri, 1 Jun 2018 07:34:13 +0100
> From: Alex Otenko <oleksandr.otenko at gmail.com>
> To: Carl Mastrangelo <notcarl at google.com>
> Cc: shevek at anarres.org, concurrency-interest at cs.oswego.edu
> Subject: Re: [concurrency-interest] Unsynchronized lazy conditions
> Message-ID: <5A23E26F-188C-4E32-8471-695A565049B1 at gmail.com>
> Content-Type: text/plain; charset="utf-8"
>
> I would not call the trick Effective Java.
>
>
> Alex
>
> > On 31 May 2018, at 21:06, Carl Mastrangelo via Concurrency-interest <
> concurrency-interest at cs.oswego.edu> wrote:
> >
> > At the cost of about 500 bytes of class size, you could do the trick in
> Effective Java:
> >
> > class Foo {
> >    private static class Logged {
> >      static void log() {}
> >
> >       static {
> >          LOG.warn("Warning");
> >       }
> >    }
> >
> >    public void run() {
> >      Logged.log();
> >    }
> > }
> >
> > On Wed, May 30, 2018 at 10:17 PM Shevek via Concurrency-interest <
> concurrency-interest at cs.oswego.edu <mailto:concurrency-interest@
> cs.oswego.edu>> 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.
> > * Any thread will issue the warning AT MOST once.
> > * Some (later) threads may not issue the warning, if the updated value
> > is flushed to the heap and they load it?
> >
> > Is there a better way to do this without sacrificing performance? Is
> > this what the mysterious AtomicBoolean.lazySet, or even
> > weakCompareAndSet is about?
> >
> > This is right in the middle of something very concurrent which runs for
> > a long time, so reducing overhead is far more important than
> > occasionally issuing too many warnings.
> >
> > Thank you.
> >
> > S.
> > _______________________________________________
> > Concurrency-interest mailing list
> > Concurrency-interest at cs.oswego.edu <mailto:Concurrency-interest@
> cs.oswego.edu>
> > http://cs.oswego.edu/mailman/listinfo/concurrency-interest <
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest>
> > _______________________________________________
> > 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/20180601/ffc2d96e/attachment-0001.html>
>
> ------------------------------
>
> Message: 2
> Date: Fri, 01 Jun 2018 21:32:47 +1000
> From: Peter <jini at zeus.net.au>
> To: concurrency-interest at cs.oswego.edu
> Subject: Re: [concurrency-interest] Unsynchronized lazy conditions
> Message-ID: <5B112EDF.60906 at zeus.net.au>
> Content-Type: text/plain; charset=UTF-8; format=flowed
>
> Agreed, I've got a class that's higly concurrent, trying to log anything
> was problematic, because of the contention it caused.  Logging can cause
> significant contention, expecially under stress, so you don't want to be
> logging unnecessarily.
>
> You know what the best solution was?  A single threaded Executor.  No
> more contention due to logging.
>
> static void log(Level level, String message, Object[] parameters,
> Throwable thrown){
>          final LogRecord record = new LogRecord(level, message);
>          record.setParameters(parameters);
>          record.setThrown(thrown);
>      logExec.submit(new Runnable(){
>          public void run() {
>          logger.log(record);
>          }
>      });
>      }
>
> On 31/05/2018 7:58 PM, Alex Otenko via Concurrency-interest wrote:
> > 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
> >> <mailto: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
> >> <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
> > http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
>
>
> ------------------------------
>
> Subject: Digest Footer
>
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
>
> ------------------------------
>
> End of Concurrency-interest Digest, Vol 161, Issue 1
> ****************************************************
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20180601/f5283964/attachment-0001.html>


More information about the Concurrency-interest mailing list