Java 同步:如何让等待线程不执行同步任务

Java synchronization: how to have waiting threads not execute the synchronized task

假设我在 Java 中有一段代码要同步执行,但是当拥有锁的线程释放该锁时,我不希望等待线程执行任何同步代码更多的。我只想让他们等到同步代码完成 运行.

因此,当线程 1 进入同步代码(方法、代码块)时,它必须获得对该代码的锁定。任何后续线程都必须等待第一个线程完成 运行 代码。至此,定期代码同步。

但是在我的例子中,当第一个线程完成并释放锁时,我希望等待的线程跳过那段同步代码(代码更新所有线程使用的资源)。

我将如何使用同步功能在 Java 中创建它?目前我没有使用同步功能,而是使用一个持有锁(上下文)的并发集合,如下所示。然而,锁定的过程仍然需要以某种方式同步,因为两个线程能够在上下文上获得锁。

干杯!

凯耶尔德

    /*
     * A concurrently accessible set of contexts.
     */
    private static final Set<String> LOCKED_CONTEXTS;

    static {
        LOCKED_CONTEXTS = ConcurrentHashMap.newKeySet(); // meanwhile, I replaced this with Collections.synchronizedSet(new HashSet<>()) 
    }

...

        if (!LOCKED_CONTEXTS.contains(context)) {

            LOCKED_CONTEXTS.add(context);
            log.debug("Locked context: {}", context);

            try {
                doTask();

            } finally {

                LOCKED_CONTEXTS.remove(context);
                log.debug("Released context: {}", context);
            }
        } else {

            log.debug("Waiting for context to be released: {}", context);

            while (LOCKED_CONTEXTS.contains(context)) {
            }

            log.debug("The waiting is over, context is released: {}", context);
        }

我想你想把锁和信号量结合起来。

  • tryLock上锁
  • 如果你明白了,那就去做吧。工作结束时,将信号量标记为完成
  • 如果没有获取到,等待信号量完成

也许我不完全理解你的use-case,但据我所知,你想要一段代码在执行期间对所有触发器只运行一次,但如果有任何触发器则再次发生在上次执行之外 window.

这涵盖了吗?

class Work {
  private volatile boolean done;

  void queueWorkOnce() {
    done = false;
    actualWork();
  }

  private synchronized void actualWork() {
    if (!done) {
      //TODO: do work
      done = true;
    }
  }
}