Conditionally define synchronized block
Asked Answered
F

1

9

Say I have a method:

public void run(){
  synchronized(this.foo){

 }
}

but sometimes when I run this method, I don't need to synchronize on anything.

What is a good pattern to conditionally synchronize on something? The only pattern I can think of is a callback, something like this:

public void conditionalSync(Runnable r){
   if(bar){
      r.run();
      return;
   }

  synchronized(this.foo){
     r.run();
  }
}

public void run(){
  this.conditionalSync(()->{


  });
}

is there another way to do it, without a callback?

Fatherless answered 22/2, 2019 at 1:28 Comment(0)
F
7

Instead of synchronized keyword, maybe you can use ReentrantLock(which is more flexible and powerful).

Example:

ReentrantLock lock = ...;


public void run(){
    if (bar) {
        lock.lock();
    }

    try {
        // do something

    } finally {
        if (lock.isHeldByCurrentThread()) {
            lock.unlock();
        }
    }
}
Foreshadow answered 22/2, 2019 at 1:46 Comment(3)
is there a way to "automate" the isHeldByCurrentThread check? is there some method that contains that check? Probably want to check for bar too in the finally block, if bar is false, then don't need to unlock.Fatherless
@MrCholo I'm afraid of the answer is no. If you call unlock directly, while the thread does not hold the lock, IllegalMonitorStateException will be thrown.Foreshadow
@MrCholo since the decision to synchronize or not shouldn’t change in-between, you can express this choice via class inheritance, e.g. create a base class providing the method doing work without synchronization and a subclass overriding the method to perform the super invocation in a synchronized block or while holding a lock. That’s how StringBuffer (synchronizing) and StringBuilder (not synchronizing) have been implemented.Gob

© 2022 - 2024 — McMap. All rights reserved.