简体   繁体   English

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

[英]Asynchronous (non-blocking) version of synchronized(){}

Is there a good way to implement an asynchronous version of synchronized keyword? 有没有一种很好的方法来实现synchronized关键字的异步版本? Obviously the synchronized() keyword will frequently block the current thread. 显然,synchronized()关键字会频繁地阻塞当前线程。 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. 我编写了Object.onLockAcquisition方法,但是找了类似的东西。

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) 双锁定替代方案(使用volatile + monitor并检查volatile两次,一次锁定前,一次锁定后)
  • use AtomicXXX and there compareAndSet/compareAndExchange etc.. methods 使用AtomicXXX和compareAndSet / compareAndExchange等方法
  • use the java.util.concurrent.locks 使用java.util.concurrent.locks
  • use a single threaded executor to execute the critical section 使用单线程执行程序来执行临界区
  • use a queue 使用队列

The correct solution in terms of Vert.x would be to use SharedData.getLock() Vert.x的正确解决方案是使用SharedData.getLock()
Reason for that is that asynchronicity is part of a specific library, and not of JVM platform. 原因是异步性是特定库的一部分,而不是JVM平台的一部分。

Unless Vert.x runs in a clustered mode, it will fall back to local lock: 除非Vert.x以集群模式运行,否则它将回退到本地锁:

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

getLock uses LocalAsyncLocal underneath: getLock使用下面的LocalAsyncLocal

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 acquire()使用ConcurrentHashMap.computehttps//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. 因此,如果您真的想拥有自己的实现,可以从上面的代码中获取灵感。

One solution in Vertx is the toolkit's asynchronous locking calls: Vertx中的一个解决方案是工具包的异步锁定调用:

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

which looks like: 看起来像:

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

however, this is not really the solution I am looking for, as this is a networked lock, which means it's pretty slow compared to a normal in-memory lock. 然而,这并不是我想要的解决方案,因为这是一个网络锁,这意味着它与普通的内存锁相比非常慢。 I only need to create a lock in a single thread not across threads or processes. 我只需要在单个线程中创建一个锁,而不是跨线程或进程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM