[concurrency-interest] Unsynchronized lazy conditions

Peter jini at zeus.net.au
Fri Jun 1 07:32:47 EDT 2018


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



More information about the Concurrency-interest mailing list