Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asynchronous (non-blocking) version of synchronized(){}

Tags:

java

akka

vert.x

Is there a good way to implement an asynchronous version of synchronized keyword? Obviously the synchronized() keyword will frequently block the current thread. For example:

  public static boolean getLockSync(Runnable r) {

    if (isLocked) {
      r.run();
      return true;
    }

    synchronized (My.lock) { // this is blocking, could block for more than 1-2 ms
      isLocked = true;
      r.run();
      isLocked = false;
      return false;
    }

  }

I can return a boolean from this block - it's synchronous. Is there a way to do this asynchronously?

Something like this:

  public static void getLockAsync(Runnable r) {

    if (isLocked) {
      CompletableFuture.runAsync(r);
      return;
    }

    Object.onLockAcquisition(My.lock, () -> { // this is non-blocking
           isLocked = true;
           r.run();
           isLocked = false;
           Object.releaseLock(My.lock);
     });

  }

I made up the Object.onLockAcquisition method, but looking for something like that.

like image 876
Alexander Mills Avatar asked Feb 07 '19 07:02

Alexander Mills


2 Answers

The correct solution in terms of Vert.x would be to use SharedData.getLock()
Reason for that is that asynchronicity is part of a specific library, and not of JVM platform.

Unless Vert.x runs in a clustered mode, it will fall back to local lock:

public void getLockWithTimeout(String name, long timeout, Handler<AsyncResult<Lock>> resultHandler) {
    ...
    if (clusterManager == null) {
      getLocalLock(name, timeout, resultHandler);
    } else {
      ...
    }
  }

getLock uses LocalAsyncLocal underneath:

localAsyncLocks.acquire(vertx.getOrCreateContext(), name, timeout, resultHandler);

acquire() uses ConcurrentHashMap.compute under the hood: https://github.com/eclipse-vertx/vert.x/blob/master/src/main/java/io/vertx/core/shareddata/impl/LocalAsyncLocks.java#L91

So if you really want to have your own implementation, you can take inspiration from the code above.

like image 117
Alexey Soshin Avatar answered Sep 21 '22 16:09

Alexey Soshin


Have you investigated alternatives? Depending what you're trying to achieve then one - or a combination - of the following might help (or not):

  • double locking alternatives (using volatile + monitor and check the volatile twice, once before locking, once after locking)
  • use AtomicXXX and there compareAndSet/compareAndExchange etc.. methods
  • use the java.util.concurrent.locks
  • use a single threaded executor to execute the critical section
  • use a queue
like image 32
daniel Avatar answered Sep 19 '22 16:09

daniel