sync()的异步(非阻塞)版本{}

时间:2019-02-07 07:44:10

标签: java akka vert.x

是否有一个很好的方法来实现synced关键字的异步版本?显然,关键字synchronized()经常会阻塞当前线程。例如:

  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;
    }

  }

我可以从该块返回一个布尔值-它是同步的。有异步的方法吗?

类似这样的东西:

  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);
     });

  }

我组成了Object.onLockAcquisition方法,但是正在寻找类似的东西。

3 个答案:

答案 0 :(得分:6)

您是否研究过替代品?根据您要实现的目标,以下一项或多项措施可能有帮助(或没有帮助):

  • 双重锁定替代方法(使用volatile +监视程序并两次检查volatile,锁定之前一次,锁定之后一次)
  • 使用AtomicXXX并使用compareAndSet / compareAndExchange等方法。
  • 使用java.util.concurrent.locks
  • 使用单线程执行器执行关键部分
  • 使用队列

答案 1 :(得分:6)

就Vert.x而言,正确的解决方案是使用SharedData.getLock()
原因是异步性是特定库的一部分,而不是JVM平台的一部分。

除非Vert.x以群集模式运行,否则它将退回到本地锁定:

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

getLock在下面使用LocalAsyncLocal

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

acquire()在后​​台使用ConcurrentHashMap.computehttps://github.com/eclipse-vertx/vert.x/blob/master/src/main/java/io/vertx/core/shareddata/impl/LocalAsyncLocks.java#L91

因此,如果您真的想拥有自己的实现,则可以从上面的代码中汲取灵感。

答案 2 :(得分:5)

Vertx中的一种解决方案是工具包的异步锁定调用:

https://vertx.io/docs/vertx-core/java/#_asynchronous_locks

如下所示:

sd.getLock("mylock", res -> {
   Lock lock = res.result();
   vertx.setTimer(5000, tid -> lock.release());
});

但是,这不是不是我真正想要的解决方案,因为这是一个网络锁,这意味着它与普通的内存锁相比非常慢。我只需要在单个线程中创建锁,而无需跨线程或进程。