Java concurrency: resettable enabled/disabled wait condition












4















I want to let a thread sleep until a certain condition becomes off. Basically, I need three operations:





  • enable(): enable sleeping mode (do nothing if already enabled)


  • disable(): disable sleeping mode (do nothing if already disabled)


  • await(): wait until sleeping mode becomes disabled (or return immediately if the sleeping mode was already disabled) or the thread becomes interrupted (InterruptedException is thrown)


With this, thread A calls enable(). Now thread B calls await() and goes to sleep until thread A (or another one) calls disable(). This cycle can be repeated.



I know this can be quite easily done with wait() and notify(), but I am wondering if JDK8 has such functionality built-in?



The closest I could find is was a CountdownLatch(1), unfortunately the implementation is not resettable.



Basically, I just want to call enable()/disable() and await(), while all concurrency concepts are abstracted in the implementation (though await() should throw InterruptedException, which is unavoidable).










share|improve this question

























  • Lock should work, eg ReentrantLock.

    – daniu
    Nov 22 '18 at 10:20











  • @daniu With Lock, I believe I still have to model the wait condition myself. All a Lock does is providing a critical section to manipulate that wait condition and inform waiting parties safely, as far as I know. Basically, I just want to call enable()/disable() and await(), while all concurrency concepts are abstracted in the implementation (though await() should throw InterruptedException, which is unavoidable).

    – OneLastSpark
    Nov 22 '18 at 10:24


















4















I want to let a thread sleep until a certain condition becomes off. Basically, I need three operations:





  • enable(): enable sleeping mode (do nothing if already enabled)


  • disable(): disable sleeping mode (do nothing if already disabled)


  • await(): wait until sleeping mode becomes disabled (or return immediately if the sleeping mode was already disabled) or the thread becomes interrupted (InterruptedException is thrown)


With this, thread A calls enable(). Now thread B calls await() and goes to sleep until thread A (or another one) calls disable(). This cycle can be repeated.



I know this can be quite easily done with wait() and notify(), but I am wondering if JDK8 has such functionality built-in?



The closest I could find is was a CountdownLatch(1), unfortunately the implementation is not resettable.



Basically, I just want to call enable()/disable() and await(), while all concurrency concepts are abstracted in the implementation (though await() should throw InterruptedException, which is unavoidable).










share|improve this question

























  • Lock should work, eg ReentrantLock.

    – daniu
    Nov 22 '18 at 10:20











  • @daniu With Lock, I believe I still have to model the wait condition myself. All a Lock does is providing a critical section to manipulate that wait condition and inform waiting parties safely, as far as I know. Basically, I just want to call enable()/disable() and await(), while all concurrency concepts are abstracted in the implementation (though await() should throw InterruptedException, which is unavoidable).

    – OneLastSpark
    Nov 22 '18 at 10:24
















4












4








4








I want to let a thread sleep until a certain condition becomes off. Basically, I need three operations:





  • enable(): enable sleeping mode (do nothing if already enabled)


  • disable(): disable sleeping mode (do nothing if already disabled)


  • await(): wait until sleeping mode becomes disabled (or return immediately if the sleeping mode was already disabled) or the thread becomes interrupted (InterruptedException is thrown)


With this, thread A calls enable(). Now thread B calls await() and goes to sleep until thread A (or another one) calls disable(). This cycle can be repeated.



I know this can be quite easily done with wait() and notify(), but I am wondering if JDK8 has such functionality built-in?



The closest I could find is was a CountdownLatch(1), unfortunately the implementation is not resettable.



Basically, I just want to call enable()/disable() and await(), while all concurrency concepts are abstracted in the implementation (though await() should throw InterruptedException, which is unavoidable).










share|improve this question
















I want to let a thread sleep until a certain condition becomes off. Basically, I need three operations:





  • enable(): enable sleeping mode (do nothing if already enabled)


  • disable(): disable sleeping mode (do nothing if already disabled)


  • await(): wait until sleeping mode becomes disabled (or return immediately if the sleeping mode was already disabled) or the thread becomes interrupted (InterruptedException is thrown)


With this, thread A calls enable(). Now thread B calls await() and goes to sleep until thread A (or another one) calls disable(). This cycle can be repeated.



I know this can be quite easily done with wait() and notify(), but I am wondering if JDK8 has such functionality built-in?



The closest I could find is was a CountdownLatch(1), unfortunately the implementation is not resettable.



Basically, I just want to call enable()/disable() and await(), while all concurrency concepts are abstracted in the implementation (though await() should throw InterruptedException, which is unavoidable).







java multithreading concurrency java.util.concurrent






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 22 '18 at 10:39







OneLastSpark

















asked Nov 22 '18 at 10:13









OneLastSparkOneLastSpark

386




386













  • Lock should work, eg ReentrantLock.

    – daniu
    Nov 22 '18 at 10:20











  • @daniu With Lock, I believe I still have to model the wait condition myself. All a Lock does is providing a critical section to manipulate that wait condition and inform waiting parties safely, as far as I know. Basically, I just want to call enable()/disable() and await(), while all concurrency concepts are abstracted in the implementation (though await() should throw InterruptedException, which is unavoidable).

    – OneLastSpark
    Nov 22 '18 at 10:24





















  • Lock should work, eg ReentrantLock.

    – daniu
    Nov 22 '18 at 10:20











  • @daniu With Lock, I believe I still have to model the wait condition myself. All a Lock does is providing a critical section to manipulate that wait condition and inform waiting parties safely, as far as I know. Basically, I just want to call enable()/disable() and await(), while all concurrency concepts are abstracted in the implementation (though await() should throw InterruptedException, which is unavoidable).

    – OneLastSpark
    Nov 22 '18 at 10:24



















Lock should work, eg ReentrantLock.

– daniu
Nov 22 '18 at 10:20





Lock should work, eg ReentrantLock.

– daniu
Nov 22 '18 at 10:20













@daniu With Lock, I believe I still have to model the wait condition myself. All a Lock does is providing a critical section to manipulate that wait condition and inform waiting parties safely, as far as I know. Basically, I just want to call enable()/disable() and await(), while all concurrency concepts are abstracted in the implementation (though await() should throw InterruptedException, which is unavoidable).

– OneLastSpark
Nov 22 '18 at 10:24







@daniu With Lock, I believe I still have to model the wait condition myself. All a Lock does is providing a critical section to manipulate that wait condition and inform waiting parties safely, as far as I know. Basically, I just want to call enable()/disable() and await(), while all concurrency concepts are abstracted in the implementation (though await() should throw InterruptedException, which is unavoidable).

– OneLastSpark
Nov 22 '18 at 10:24














4 Answers
4






active

oldest

votes


















1














Another possible implementation of Switch:



public class Switch {
private final AtomicBoolean state = new AtomicBoolean();

public void enable() {
state.set(true);
}

public void disable() {
if (state.compareAndSet(true, false)) {
synchronized (state) {
state.notifyAll();
}
}
}

public void await() throws InterruptedException {
if (state.get()) {
synchronized (state) {
while (state.get()) {
state.wait();
}
}
}
}
}





share|improve this answer































    1














    You could use a Semaphor too :



    import java.util.concurrent.Semaphore;

    public class Switch {

    private Semaphore semaphore = new Semaphore(1);

    public void enable() {
    synchronized(this) {
    semaphore.drainPermits(); // 0
    semaphore.reducePermits(1); // -1 or 0
    }
    }

    public void disable() {
    semaphore.release(2); // 1 or 2
    }

    public void await() throws InterruptedException {
    semaphore.acquire();
    semaphore.release();
    }


    }





    share|improve this answer


























    • This comes closest to that I wanted. I was hoping such Switch implementation already existed in the concurrent package.

      – OneLastSpark
      Nov 23 '18 at 18:03











    • As an afterthought, this solution is not correct. There is a small chance that enable() will be called between the two operations in await(). In that case, enable() will be ignored. I think it can be solved by adding a spin wait loop in enable(): while(semaphore.drainPermits() == 0) { Thread.yield(); }.

      – OneLastSpark
      Nov 26 '18 at 19:32











    • In JDK9, we can do Thread.onSpinWait() instead of Thread.yield().

      – OneLastSpark
      Nov 26 '18 at 19:33











    • indeed. The issue with Thread.yield is that if you call enable() while the sleep mode is already enabled, the method won't return. I think we can avoid the issue by incrementing the number of permits for enable / disable action to 2. (see update) (but we need to prevent 2 simultaneous calls to enable to avoid going down to -2)

      – Thierry
      Nov 26 '18 at 23:01





















    0














    You could use Condition :



    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;

    public class Switch {
    private final Lock lock = new ReentrantLock();
    private final Condition on = lock.newCondition();
    private final Condition off = lock.newCondition();
    private volatile boolean state = true;

    public void enable() {
    try {
    lock.lock();
    state = true;
    on.signalAll();
    } finally {
    lock.unlock();
    }
    }

    public void disable() {
    try {
    lock.lock();
    state = false;
    off.signalAll();
    } finally {
    lock.unlock();
    }
    }

    public void await() {
    try {
    lock.lock();
    while(!state) {
    try {
    off.await();
    } catch (InterruptedException e) {
    throw new RuntimeException("waiting interrupted.");
    }
    }
    } finally {
    lock.unlock();
    }
    }
    }





    share|improve this answer
























    • I would upvote this as well, but this has a few problems. First, it's better to let await() just throw the InterruptedException. There is no need to translate to a RuntimeException. If you still decide to do that however, you have to reset the interrupted flag before throwing the RuntimeException. Second, you are signaling the on lock, but nobody is ever waiting on that. You can remove that. Third, there is no need to make state volatile, as it is already guarded by the memory barrier set by the lock.

      – OneLastSpark
      Nov 23 '18 at 18:06











    • Also, another downside of this implementation is that for every await() call, a lock must be acquired. Your other answer (Semaphore based) and my answer do not suffer from that. Both have some kind of fail-fast path, which relies on volatile visibility. This is usually a bit faster than acquiring a lock each time.

      – OneLastSpark
      Nov 23 '18 at 18:46





















    0














    enable(): enable sleeping mode (do nothing if already enabled)
    disable(): disable sleeping mode (do nothing if already disabled)


    do nothing if already enabled (disabled) is a bad design, which can lead to subtle bugs which are hard to reproduce and discover. For example, let sleeping mode is disabled, and one thread calls disable() and the other calls enable(). Depending on which call is made first, the mode will stay enabled or disabled forever. To make execution more deterministic, enabling and disabling must be counted, and the final state will be determined (disabled).



    Instead, your threads should exchange tokens which do not mask each other. Besides CountdownLatch, (which effectively is a counter of prohibitions), JDK has CyclicBarrier and Phaser, which are resettable counters of prohibitions, and Semaphore, which is a counter of permissions.



    UPDT
    this implementation may work (I did not tested it):



    Phaser p = new Phaser(1);

    public void await() {
    p.arriveAndAwaitAdvance();
    }

    public void enable() {
    p.register();
    }

    public void disable() {
    p.arriveAndDeregister();
    }


    N sequential calls to enable() require the same number of disable() to pass the awaiting thread.






    share|improve this answer


























    • Could you show how you would implement what @OneLastSpark asks with one of the three classes you mention ? (CyclicBarrier, Phaser or Semaphor) ? I tried to come up to something with one of these, but there was always a use case that would not work with these (in particular during the switch off of the sleeping mode when the thread B was not waiting already)

      – Thierry
      Nov 22 '18 at 15:44






    • 1





      In the question : until thread A (or another one) calls disable(). But arriveAndDeregister() (disable()) must be called by the thread that called register() (enable())

      – Thierry
      Nov 23 '18 at 13:40






    • 1





      Also, if two different threads calls the enable() method both will have to call the disable() method for the await to end. Which implies that calling the enable() method should be done in a try and the disable() method in the finally block otherwise the switch will be blocked longer than intended (potentially until jvm stops).

      – Thierry
      Nov 23 '18 at 13:58











    • @Thierry looks like you are right.

      – Alexei Kaigorodov
      Nov 23 '18 at 14:26











    • I understand you concerns and remark regarding passing a token, but this is not really applicable to my question. I have no token to pass, and I never ever want enable() or disable() to block. Thierry's concerns are spot on.

      – OneLastSpark
      Nov 23 '18 at 18:14











    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53428589%2fjava-concurrency-resettable-enabled-disabled-wait-condition%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    Another possible implementation of Switch:



    public class Switch {
    private final AtomicBoolean state = new AtomicBoolean();

    public void enable() {
    state.set(true);
    }

    public void disable() {
    if (state.compareAndSet(true, false)) {
    synchronized (state) {
    state.notifyAll();
    }
    }
    }

    public void await() throws InterruptedException {
    if (state.get()) {
    synchronized (state) {
    while (state.get()) {
    state.wait();
    }
    }
    }
    }
    }





    share|improve this answer




























      1














      Another possible implementation of Switch:



      public class Switch {
      private final AtomicBoolean state = new AtomicBoolean();

      public void enable() {
      state.set(true);
      }

      public void disable() {
      if (state.compareAndSet(true, false)) {
      synchronized (state) {
      state.notifyAll();
      }
      }
      }

      public void await() throws InterruptedException {
      if (state.get()) {
      synchronized (state) {
      while (state.get()) {
      state.wait();
      }
      }
      }
      }
      }





      share|improve this answer


























        1












        1








        1







        Another possible implementation of Switch:



        public class Switch {
        private final AtomicBoolean state = new AtomicBoolean();

        public void enable() {
        state.set(true);
        }

        public void disable() {
        if (state.compareAndSet(true, false)) {
        synchronized (state) {
        state.notifyAll();
        }
        }
        }

        public void await() throws InterruptedException {
        if (state.get()) {
        synchronized (state) {
        while (state.get()) {
        state.wait();
        }
        }
        }
        }
        }





        share|improve this answer













        Another possible implementation of Switch:



        public class Switch {
        private final AtomicBoolean state = new AtomicBoolean();

        public void enable() {
        state.set(true);
        }

        public void disable() {
        if (state.compareAndSet(true, false)) {
        synchronized (state) {
        state.notifyAll();
        }
        }
        }

        public void await() throws InterruptedException {
        if (state.get()) {
        synchronized (state) {
        while (state.get()) {
        state.wait();
        }
        }
        }
        }
        }






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 23 '18 at 18:30









        OneLastSparkOneLastSpark

        386




        386

























            1














            You could use a Semaphor too :



            import java.util.concurrent.Semaphore;

            public class Switch {

            private Semaphore semaphore = new Semaphore(1);

            public void enable() {
            synchronized(this) {
            semaphore.drainPermits(); // 0
            semaphore.reducePermits(1); // -1 or 0
            }
            }

            public void disable() {
            semaphore.release(2); // 1 or 2
            }

            public void await() throws InterruptedException {
            semaphore.acquire();
            semaphore.release();
            }


            }





            share|improve this answer


























            • This comes closest to that I wanted. I was hoping such Switch implementation already existed in the concurrent package.

              – OneLastSpark
              Nov 23 '18 at 18:03











            • As an afterthought, this solution is not correct. There is a small chance that enable() will be called between the two operations in await(). In that case, enable() will be ignored. I think it can be solved by adding a spin wait loop in enable(): while(semaphore.drainPermits() == 0) { Thread.yield(); }.

              – OneLastSpark
              Nov 26 '18 at 19:32











            • In JDK9, we can do Thread.onSpinWait() instead of Thread.yield().

              – OneLastSpark
              Nov 26 '18 at 19:33











            • indeed. The issue with Thread.yield is that if you call enable() while the sleep mode is already enabled, the method won't return. I think we can avoid the issue by incrementing the number of permits for enable / disable action to 2. (see update) (but we need to prevent 2 simultaneous calls to enable to avoid going down to -2)

              – Thierry
              Nov 26 '18 at 23:01


















            1














            You could use a Semaphor too :



            import java.util.concurrent.Semaphore;

            public class Switch {

            private Semaphore semaphore = new Semaphore(1);

            public void enable() {
            synchronized(this) {
            semaphore.drainPermits(); // 0
            semaphore.reducePermits(1); // -1 or 0
            }
            }

            public void disable() {
            semaphore.release(2); // 1 or 2
            }

            public void await() throws InterruptedException {
            semaphore.acquire();
            semaphore.release();
            }


            }





            share|improve this answer


























            • This comes closest to that I wanted. I was hoping such Switch implementation already existed in the concurrent package.

              – OneLastSpark
              Nov 23 '18 at 18:03











            • As an afterthought, this solution is not correct. There is a small chance that enable() will be called between the two operations in await(). In that case, enable() will be ignored. I think it can be solved by adding a spin wait loop in enable(): while(semaphore.drainPermits() == 0) { Thread.yield(); }.

              – OneLastSpark
              Nov 26 '18 at 19:32











            • In JDK9, we can do Thread.onSpinWait() instead of Thread.yield().

              – OneLastSpark
              Nov 26 '18 at 19:33











            • indeed. The issue with Thread.yield is that if you call enable() while the sleep mode is already enabled, the method won't return. I think we can avoid the issue by incrementing the number of permits for enable / disable action to 2. (see update) (but we need to prevent 2 simultaneous calls to enable to avoid going down to -2)

              – Thierry
              Nov 26 '18 at 23:01
















            1












            1








            1







            You could use a Semaphor too :



            import java.util.concurrent.Semaphore;

            public class Switch {

            private Semaphore semaphore = new Semaphore(1);

            public void enable() {
            synchronized(this) {
            semaphore.drainPermits(); // 0
            semaphore.reducePermits(1); // -1 or 0
            }
            }

            public void disable() {
            semaphore.release(2); // 1 or 2
            }

            public void await() throws InterruptedException {
            semaphore.acquire();
            semaphore.release();
            }


            }





            share|improve this answer















            You could use a Semaphor too :



            import java.util.concurrent.Semaphore;

            public class Switch {

            private Semaphore semaphore = new Semaphore(1);

            public void enable() {
            synchronized(this) {
            semaphore.drainPermits(); // 0
            semaphore.reducePermits(1); // -1 or 0
            }
            }

            public void disable() {
            semaphore.release(2); // 1 or 2
            }

            public void await() throws InterruptedException {
            semaphore.acquire();
            semaphore.release();
            }


            }






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 26 '18 at 23:03

























            answered Nov 23 '18 at 14:27









            ThierryThierry

            3,6822129




            3,6822129













            • This comes closest to that I wanted. I was hoping such Switch implementation already existed in the concurrent package.

              – OneLastSpark
              Nov 23 '18 at 18:03











            • As an afterthought, this solution is not correct. There is a small chance that enable() will be called between the two operations in await(). In that case, enable() will be ignored. I think it can be solved by adding a spin wait loop in enable(): while(semaphore.drainPermits() == 0) { Thread.yield(); }.

              – OneLastSpark
              Nov 26 '18 at 19:32











            • In JDK9, we can do Thread.onSpinWait() instead of Thread.yield().

              – OneLastSpark
              Nov 26 '18 at 19:33











            • indeed. The issue with Thread.yield is that if you call enable() while the sleep mode is already enabled, the method won't return. I think we can avoid the issue by incrementing the number of permits for enable / disable action to 2. (see update) (but we need to prevent 2 simultaneous calls to enable to avoid going down to -2)

              – Thierry
              Nov 26 '18 at 23:01





















            • This comes closest to that I wanted. I was hoping such Switch implementation already existed in the concurrent package.

              – OneLastSpark
              Nov 23 '18 at 18:03











            • As an afterthought, this solution is not correct. There is a small chance that enable() will be called between the two operations in await(). In that case, enable() will be ignored. I think it can be solved by adding a spin wait loop in enable(): while(semaphore.drainPermits() == 0) { Thread.yield(); }.

              – OneLastSpark
              Nov 26 '18 at 19:32











            • In JDK9, we can do Thread.onSpinWait() instead of Thread.yield().

              – OneLastSpark
              Nov 26 '18 at 19:33











            • indeed. The issue with Thread.yield is that if you call enable() while the sleep mode is already enabled, the method won't return. I think we can avoid the issue by incrementing the number of permits for enable / disable action to 2. (see update) (but we need to prevent 2 simultaneous calls to enable to avoid going down to -2)

              – Thierry
              Nov 26 '18 at 23:01



















            This comes closest to that I wanted. I was hoping such Switch implementation already existed in the concurrent package.

            – OneLastSpark
            Nov 23 '18 at 18:03





            This comes closest to that I wanted. I was hoping such Switch implementation already existed in the concurrent package.

            – OneLastSpark
            Nov 23 '18 at 18:03













            As an afterthought, this solution is not correct. There is a small chance that enable() will be called between the two operations in await(). In that case, enable() will be ignored. I think it can be solved by adding a spin wait loop in enable(): while(semaphore.drainPermits() == 0) { Thread.yield(); }.

            – OneLastSpark
            Nov 26 '18 at 19:32





            As an afterthought, this solution is not correct. There is a small chance that enable() will be called between the two operations in await(). In that case, enable() will be ignored. I think it can be solved by adding a spin wait loop in enable(): while(semaphore.drainPermits() == 0) { Thread.yield(); }.

            – OneLastSpark
            Nov 26 '18 at 19:32













            In JDK9, we can do Thread.onSpinWait() instead of Thread.yield().

            – OneLastSpark
            Nov 26 '18 at 19:33





            In JDK9, we can do Thread.onSpinWait() instead of Thread.yield().

            – OneLastSpark
            Nov 26 '18 at 19:33













            indeed. The issue with Thread.yield is that if you call enable() while the sleep mode is already enabled, the method won't return. I think we can avoid the issue by incrementing the number of permits for enable / disable action to 2. (see update) (but we need to prevent 2 simultaneous calls to enable to avoid going down to -2)

            – Thierry
            Nov 26 '18 at 23:01







            indeed. The issue with Thread.yield is that if you call enable() while the sleep mode is already enabled, the method won't return. I think we can avoid the issue by incrementing the number of permits for enable / disable action to 2. (see update) (but we need to prevent 2 simultaneous calls to enable to avoid going down to -2)

            – Thierry
            Nov 26 '18 at 23:01













            0














            You could use Condition :



            import java.util.concurrent.locks.Condition;
            import java.util.concurrent.locks.Lock;
            import java.util.concurrent.locks.ReentrantLock;

            public class Switch {
            private final Lock lock = new ReentrantLock();
            private final Condition on = lock.newCondition();
            private final Condition off = lock.newCondition();
            private volatile boolean state = true;

            public void enable() {
            try {
            lock.lock();
            state = true;
            on.signalAll();
            } finally {
            lock.unlock();
            }
            }

            public void disable() {
            try {
            lock.lock();
            state = false;
            off.signalAll();
            } finally {
            lock.unlock();
            }
            }

            public void await() {
            try {
            lock.lock();
            while(!state) {
            try {
            off.await();
            } catch (InterruptedException e) {
            throw new RuntimeException("waiting interrupted.");
            }
            }
            } finally {
            lock.unlock();
            }
            }
            }





            share|improve this answer
























            • I would upvote this as well, but this has a few problems. First, it's better to let await() just throw the InterruptedException. There is no need to translate to a RuntimeException. If you still decide to do that however, you have to reset the interrupted flag before throwing the RuntimeException. Second, you are signaling the on lock, but nobody is ever waiting on that. You can remove that. Third, there is no need to make state volatile, as it is already guarded by the memory barrier set by the lock.

              – OneLastSpark
              Nov 23 '18 at 18:06











            • Also, another downside of this implementation is that for every await() call, a lock must be acquired. Your other answer (Semaphore based) and my answer do not suffer from that. Both have some kind of fail-fast path, which relies on volatile visibility. This is usually a bit faster than acquiring a lock each time.

              – OneLastSpark
              Nov 23 '18 at 18:46


















            0














            You could use Condition :



            import java.util.concurrent.locks.Condition;
            import java.util.concurrent.locks.Lock;
            import java.util.concurrent.locks.ReentrantLock;

            public class Switch {
            private final Lock lock = new ReentrantLock();
            private final Condition on = lock.newCondition();
            private final Condition off = lock.newCondition();
            private volatile boolean state = true;

            public void enable() {
            try {
            lock.lock();
            state = true;
            on.signalAll();
            } finally {
            lock.unlock();
            }
            }

            public void disable() {
            try {
            lock.lock();
            state = false;
            off.signalAll();
            } finally {
            lock.unlock();
            }
            }

            public void await() {
            try {
            lock.lock();
            while(!state) {
            try {
            off.await();
            } catch (InterruptedException e) {
            throw new RuntimeException("waiting interrupted.");
            }
            }
            } finally {
            lock.unlock();
            }
            }
            }





            share|improve this answer
























            • I would upvote this as well, but this has a few problems. First, it's better to let await() just throw the InterruptedException. There is no need to translate to a RuntimeException. If you still decide to do that however, you have to reset the interrupted flag before throwing the RuntimeException. Second, you are signaling the on lock, but nobody is ever waiting on that. You can remove that. Third, there is no need to make state volatile, as it is already guarded by the memory barrier set by the lock.

              – OneLastSpark
              Nov 23 '18 at 18:06











            • Also, another downside of this implementation is that for every await() call, a lock must be acquired. Your other answer (Semaphore based) and my answer do not suffer from that. Both have some kind of fail-fast path, which relies on volatile visibility. This is usually a bit faster than acquiring a lock each time.

              – OneLastSpark
              Nov 23 '18 at 18:46
















            0












            0








            0







            You could use Condition :



            import java.util.concurrent.locks.Condition;
            import java.util.concurrent.locks.Lock;
            import java.util.concurrent.locks.ReentrantLock;

            public class Switch {
            private final Lock lock = new ReentrantLock();
            private final Condition on = lock.newCondition();
            private final Condition off = lock.newCondition();
            private volatile boolean state = true;

            public void enable() {
            try {
            lock.lock();
            state = true;
            on.signalAll();
            } finally {
            lock.unlock();
            }
            }

            public void disable() {
            try {
            lock.lock();
            state = false;
            off.signalAll();
            } finally {
            lock.unlock();
            }
            }

            public void await() {
            try {
            lock.lock();
            while(!state) {
            try {
            off.await();
            } catch (InterruptedException e) {
            throw new RuntimeException("waiting interrupted.");
            }
            }
            } finally {
            lock.unlock();
            }
            }
            }





            share|improve this answer













            You could use Condition :



            import java.util.concurrent.locks.Condition;
            import java.util.concurrent.locks.Lock;
            import java.util.concurrent.locks.ReentrantLock;

            public class Switch {
            private final Lock lock = new ReentrantLock();
            private final Condition on = lock.newCondition();
            private final Condition off = lock.newCondition();
            private volatile boolean state = true;

            public void enable() {
            try {
            lock.lock();
            state = true;
            on.signalAll();
            } finally {
            lock.unlock();
            }
            }

            public void disable() {
            try {
            lock.lock();
            state = false;
            off.signalAll();
            } finally {
            lock.unlock();
            }
            }

            public void await() {
            try {
            lock.lock();
            while(!state) {
            try {
            off.await();
            } catch (InterruptedException e) {
            throw new RuntimeException("waiting interrupted.");
            }
            }
            } finally {
            lock.unlock();
            }
            }
            }






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 22 '18 at 10:57









            ThierryThierry

            3,6822129




            3,6822129













            • I would upvote this as well, but this has a few problems. First, it's better to let await() just throw the InterruptedException. There is no need to translate to a RuntimeException. If you still decide to do that however, you have to reset the interrupted flag before throwing the RuntimeException. Second, you are signaling the on lock, but nobody is ever waiting on that. You can remove that. Third, there is no need to make state volatile, as it is already guarded by the memory barrier set by the lock.

              – OneLastSpark
              Nov 23 '18 at 18:06











            • Also, another downside of this implementation is that for every await() call, a lock must be acquired. Your other answer (Semaphore based) and my answer do not suffer from that. Both have some kind of fail-fast path, which relies on volatile visibility. This is usually a bit faster than acquiring a lock each time.

              – OneLastSpark
              Nov 23 '18 at 18:46





















            • I would upvote this as well, but this has a few problems. First, it's better to let await() just throw the InterruptedException. There is no need to translate to a RuntimeException. If you still decide to do that however, you have to reset the interrupted flag before throwing the RuntimeException. Second, you are signaling the on lock, but nobody is ever waiting on that. You can remove that. Third, there is no need to make state volatile, as it is already guarded by the memory barrier set by the lock.

              – OneLastSpark
              Nov 23 '18 at 18:06











            • Also, another downside of this implementation is that for every await() call, a lock must be acquired. Your other answer (Semaphore based) and my answer do not suffer from that. Both have some kind of fail-fast path, which relies on volatile visibility. This is usually a bit faster than acquiring a lock each time.

              – OneLastSpark
              Nov 23 '18 at 18:46



















            I would upvote this as well, but this has a few problems. First, it's better to let await() just throw the InterruptedException. There is no need to translate to a RuntimeException. If you still decide to do that however, you have to reset the interrupted flag before throwing the RuntimeException. Second, you are signaling the on lock, but nobody is ever waiting on that. You can remove that. Third, there is no need to make state volatile, as it is already guarded by the memory barrier set by the lock.

            – OneLastSpark
            Nov 23 '18 at 18:06





            I would upvote this as well, but this has a few problems. First, it's better to let await() just throw the InterruptedException. There is no need to translate to a RuntimeException. If you still decide to do that however, you have to reset the interrupted flag before throwing the RuntimeException. Second, you are signaling the on lock, but nobody is ever waiting on that. You can remove that. Third, there is no need to make state volatile, as it is already guarded by the memory barrier set by the lock.

            – OneLastSpark
            Nov 23 '18 at 18:06













            Also, another downside of this implementation is that for every await() call, a lock must be acquired. Your other answer (Semaphore based) and my answer do not suffer from that. Both have some kind of fail-fast path, which relies on volatile visibility. This is usually a bit faster than acquiring a lock each time.

            – OneLastSpark
            Nov 23 '18 at 18:46







            Also, another downside of this implementation is that for every await() call, a lock must be acquired. Your other answer (Semaphore based) and my answer do not suffer from that. Both have some kind of fail-fast path, which relies on volatile visibility. This is usually a bit faster than acquiring a lock each time.

            – OneLastSpark
            Nov 23 '18 at 18:46













            0














            enable(): enable sleeping mode (do nothing if already enabled)
            disable(): disable sleeping mode (do nothing if already disabled)


            do nothing if already enabled (disabled) is a bad design, which can lead to subtle bugs which are hard to reproduce and discover. For example, let sleeping mode is disabled, and one thread calls disable() and the other calls enable(). Depending on which call is made first, the mode will stay enabled or disabled forever. To make execution more deterministic, enabling and disabling must be counted, and the final state will be determined (disabled).



            Instead, your threads should exchange tokens which do not mask each other. Besides CountdownLatch, (which effectively is a counter of prohibitions), JDK has CyclicBarrier and Phaser, which are resettable counters of prohibitions, and Semaphore, which is a counter of permissions.



            UPDT
            this implementation may work (I did not tested it):



            Phaser p = new Phaser(1);

            public void await() {
            p.arriveAndAwaitAdvance();
            }

            public void enable() {
            p.register();
            }

            public void disable() {
            p.arriveAndDeregister();
            }


            N sequential calls to enable() require the same number of disable() to pass the awaiting thread.






            share|improve this answer


























            • Could you show how you would implement what @OneLastSpark asks with one of the three classes you mention ? (CyclicBarrier, Phaser or Semaphor) ? I tried to come up to something with one of these, but there was always a use case that would not work with these (in particular during the switch off of the sleeping mode when the thread B was not waiting already)

              – Thierry
              Nov 22 '18 at 15:44






            • 1





              In the question : until thread A (or another one) calls disable(). But arriveAndDeregister() (disable()) must be called by the thread that called register() (enable())

              – Thierry
              Nov 23 '18 at 13:40






            • 1





              Also, if two different threads calls the enable() method both will have to call the disable() method for the await to end. Which implies that calling the enable() method should be done in a try and the disable() method in the finally block otherwise the switch will be blocked longer than intended (potentially until jvm stops).

              – Thierry
              Nov 23 '18 at 13:58











            • @Thierry looks like you are right.

              – Alexei Kaigorodov
              Nov 23 '18 at 14:26











            • I understand you concerns and remark regarding passing a token, but this is not really applicable to my question. I have no token to pass, and I never ever want enable() or disable() to block. Thierry's concerns are spot on.

              – OneLastSpark
              Nov 23 '18 at 18:14
















            0














            enable(): enable sleeping mode (do nothing if already enabled)
            disable(): disable sleeping mode (do nothing if already disabled)


            do nothing if already enabled (disabled) is a bad design, which can lead to subtle bugs which are hard to reproduce and discover. For example, let sleeping mode is disabled, and one thread calls disable() and the other calls enable(). Depending on which call is made first, the mode will stay enabled or disabled forever. To make execution more deterministic, enabling and disabling must be counted, and the final state will be determined (disabled).



            Instead, your threads should exchange tokens which do not mask each other. Besides CountdownLatch, (which effectively is a counter of prohibitions), JDK has CyclicBarrier and Phaser, which are resettable counters of prohibitions, and Semaphore, which is a counter of permissions.



            UPDT
            this implementation may work (I did not tested it):



            Phaser p = new Phaser(1);

            public void await() {
            p.arriveAndAwaitAdvance();
            }

            public void enable() {
            p.register();
            }

            public void disable() {
            p.arriveAndDeregister();
            }


            N sequential calls to enable() require the same number of disable() to pass the awaiting thread.






            share|improve this answer


























            • Could you show how you would implement what @OneLastSpark asks with one of the three classes you mention ? (CyclicBarrier, Phaser or Semaphor) ? I tried to come up to something with one of these, but there was always a use case that would not work with these (in particular during the switch off of the sleeping mode when the thread B was not waiting already)

              – Thierry
              Nov 22 '18 at 15:44






            • 1





              In the question : until thread A (or another one) calls disable(). But arriveAndDeregister() (disable()) must be called by the thread that called register() (enable())

              – Thierry
              Nov 23 '18 at 13:40






            • 1





              Also, if two different threads calls the enable() method both will have to call the disable() method for the await to end. Which implies that calling the enable() method should be done in a try and the disable() method in the finally block otherwise the switch will be blocked longer than intended (potentially until jvm stops).

              – Thierry
              Nov 23 '18 at 13:58











            • @Thierry looks like you are right.

              – Alexei Kaigorodov
              Nov 23 '18 at 14:26











            • I understand you concerns and remark regarding passing a token, but this is not really applicable to my question. I have no token to pass, and I never ever want enable() or disable() to block. Thierry's concerns are spot on.

              – OneLastSpark
              Nov 23 '18 at 18:14














            0












            0








            0







            enable(): enable sleeping mode (do nothing if already enabled)
            disable(): disable sleeping mode (do nothing if already disabled)


            do nothing if already enabled (disabled) is a bad design, which can lead to subtle bugs which are hard to reproduce and discover. For example, let sleeping mode is disabled, and one thread calls disable() and the other calls enable(). Depending on which call is made first, the mode will stay enabled or disabled forever. To make execution more deterministic, enabling and disabling must be counted, and the final state will be determined (disabled).



            Instead, your threads should exchange tokens which do not mask each other. Besides CountdownLatch, (which effectively is a counter of prohibitions), JDK has CyclicBarrier and Phaser, which are resettable counters of prohibitions, and Semaphore, which is a counter of permissions.



            UPDT
            this implementation may work (I did not tested it):



            Phaser p = new Phaser(1);

            public void await() {
            p.arriveAndAwaitAdvance();
            }

            public void enable() {
            p.register();
            }

            public void disable() {
            p.arriveAndDeregister();
            }


            N sequential calls to enable() require the same number of disable() to pass the awaiting thread.






            share|improve this answer















            enable(): enable sleeping mode (do nothing if already enabled)
            disable(): disable sleeping mode (do nothing if already disabled)


            do nothing if already enabled (disabled) is a bad design, which can lead to subtle bugs which are hard to reproduce and discover. For example, let sleeping mode is disabled, and one thread calls disable() and the other calls enable(). Depending on which call is made first, the mode will stay enabled or disabled forever. To make execution more deterministic, enabling and disabling must be counted, and the final state will be determined (disabled).



            Instead, your threads should exchange tokens which do not mask each other. Besides CountdownLatch, (which effectively is a counter of prohibitions), JDK has CyclicBarrier and Phaser, which are resettable counters of prohibitions, and Semaphore, which is a counter of permissions.



            UPDT
            this implementation may work (I did not tested it):



            Phaser p = new Phaser(1);

            public void await() {
            p.arriveAndAwaitAdvance();
            }

            public void enable() {
            p.register();
            }

            public void disable() {
            p.arriveAndDeregister();
            }


            N sequential calls to enable() require the same number of disable() to pass the awaiting thread.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 23 '18 at 5:04

























            answered Nov 22 '18 at 15:39









            Alexei KaigorodovAlexei Kaigorodov

            10.1k11129




            10.1k11129













            • Could you show how you would implement what @OneLastSpark asks with one of the three classes you mention ? (CyclicBarrier, Phaser or Semaphor) ? I tried to come up to something with one of these, but there was always a use case that would not work with these (in particular during the switch off of the sleeping mode when the thread B was not waiting already)

              – Thierry
              Nov 22 '18 at 15:44






            • 1





              In the question : until thread A (or another one) calls disable(). But arriveAndDeregister() (disable()) must be called by the thread that called register() (enable())

              – Thierry
              Nov 23 '18 at 13:40






            • 1





              Also, if two different threads calls the enable() method both will have to call the disable() method for the await to end. Which implies that calling the enable() method should be done in a try and the disable() method in the finally block otherwise the switch will be blocked longer than intended (potentially until jvm stops).

              – Thierry
              Nov 23 '18 at 13:58











            • @Thierry looks like you are right.

              – Alexei Kaigorodov
              Nov 23 '18 at 14:26











            • I understand you concerns and remark regarding passing a token, but this is not really applicable to my question. I have no token to pass, and I never ever want enable() or disable() to block. Thierry's concerns are spot on.

              – OneLastSpark
              Nov 23 '18 at 18:14



















            • Could you show how you would implement what @OneLastSpark asks with one of the three classes you mention ? (CyclicBarrier, Phaser or Semaphor) ? I tried to come up to something with one of these, but there was always a use case that would not work with these (in particular during the switch off of the sleeping mode when the thread B was not waiting already)

              – Thierry
              Nov 22 '18 at 15:44






            • 1





              In the question : until thread A (or another one) calls disable(). But arriveAndDeregister() (disable()) must be called by the thread that called register() (enable())

              – Thierry
              Nov 23 '18 at 13:40






            • 1





              Also, if two different threads calls the enable() method both will have to call the disable() method for the await to end. Which implies that calling the enable() method should be done in a try and the disable() method in the finally block otherwise the switch will be blocked longer than intended (potentially until jvm stops).

              – Thierry
              Nov 23 '18 at 13:58











            • @Thierry looks like you are right.

              – Alexei Kaigorodov
              Nov 23 '18 at 14:26











            • I understand you concerns and remark regarding passing a token, but this is not really applicable to my question. I have no token to pass, and I never ever want enable() or disable() to block. Thierry's concerns are spot on.

              – OneLastSpark
              Nov 23 '18 at 18:14

















            Could you show how you would implement what @OneLastSpark asks with one of the three classes you mention ? (CyclicBarrier, Phaser or Semaphor) ? I tried to come up to something with one of these, but there was always a use case that would not work with these (in particular during the switch off of the sleeping mode when the thread B was not waiting already)

            – Thierry
            Nov 22 '18 at 15:44





            Could you show how you would implement what @OneLastSpark asks with one of the three classes you mention ? (CyclicBarrier, Phaser or Semaphor) ? I tried to come up to something with one of these, but there was always a use case that would not work with these (in particular during the switch off of the sleeping mode when the thread B was not waiting already)

            – Thierry
            Nov 22 '18 at 15:44




            1




            1





            In the question : until thread A (or another one) calls disable(). But arriveAndDeregister() (disable()) must be called by the thread that called register() (enable())

            – Thierry
            Nov 23 '18 at 13:40





            In the question : until thread A (or another one) calls disable(). But arriveAndDeregister() (disable()) must be called by the thread that called register() (enable())

            – Thierry
            Nov 23 '18 at 13:40




            1




            1





            Also, if two different threads calls the enable() method both will have to call the disable() method for the await to end. Which implies that calling the enable() method should be done in a try and the disable() method in the finally block otherwise the switch will be blocked longer than intended (potentially until jvm stops).

            – Thierry
            Nov 23 '18 at 13:58





            Also, if two different threads calls the enable() method both will have to call the disable() method for the await to end. Which implies that calling the enable() method should be done in a try and the disable() method in the finally block otherwise the switch will be blocked longer than intended (potentially until jvm stops).

            – Thierry
            Nov 23 '18 at 13:58













            @Thierry looks like you are right.

            – Alexei Kaigorodov
            Nov 23 '18 at 14:26





            @Thierry looks like you are right.

            – Alexei Kaigorodov
            Nov 23 '18 at 14:26













            I understand you concerns and remark regarding passing a token, but this is not really applicable to my question. I have no token to pass, and I never ever want enable() or disable() to block. Thierry's concerns are spot on.

            – OneLastSpark
            Nov 23 '18 at 18:14





            I understand you concerns and remark regarding passing a token, but this is not really applicable to my question. I have no token to pass, and I never ever want enable() or disable() to block. Thierry's concerns are spot on.

            – OneLastSpark
            Nov 23 '18 at 18:14


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53428589%2fjava-concurrency-resettable-enabled-disabled-wait-condition%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Costa Masnaga

            Fotorealismo

            Sidney Franklin