java - 如何让线程等待ReentrantLock被释放?

标签 java multithreading concurrency

如果一个线程已经获取了锁,我希望其他线程跳过尝试获取锁,而只是等待锁被释放,然后再继续执行。我不希望其他线程在释放锁后获取该锁。

我一直在阅读有关该主题的内容,但仍然感到困惑。

请参阅下面的通用代码片段:

private final ReentrantLock reentrantLock = new ReentrantLock();

public void aCoolMethod(){
    if (reentrantLock.tryLock() == true){
        try {
            doSomething();
        } finally {
            reentrantLock.unlock();
        }
    } else {
        // have threads wait until reentrantLock is unlocked
    }
    doSomethingElse();
}

如何让进入 else block 的线程在继续执行之前等待可重入锁解锁?

最佳答案

正如 Thilo 提到的,解决问题的更好方法是有一个关键部分,其中包含线程首先检查的标志。如果尚未设置该标志,请解决您的问题并在退出关键部分之前设置该标志。如果该标志已设置,您就知道另一个线程首先到达那里并解决了问题,因此只需退出临界区即可。

private final ReentrantLock reentrantLock = new ReentrantLock();
private boolean fixed = false;

public void aCoolMethod(){
    try {
        reentrantLock.lock();

        if (!fixed) {
            doSomething();
        }
    } finally {
        fixed = true;
        reentrantLock.unlock();
    }

    doSomethingElse();
}

或者,在没有锁的情况下,您可以使用共识对象来确定哪个线程运行 doSomething():

private final AtomicBoolean turn = new AtomicBoolean(true);
private volatile boolean done = false;

public void aCoolMethod(){
    if (turn.compareAndSet(true, false)) {
        doSomething();
        done = true;
    } else {
        while (!done) {
          // spin or wait for condition
        }
        doSomethingElse();
    }
}

关于java - 如何让线程等待ReentrantLock被释放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56159605/

相关文章:

java - 变量可能未初始化错误和一般建议

java - 如何从字符串中打印出文本

java - 如何在java中翻译嵌套的 Elasticsearch 查询?

java - 在 Talend 作业中使用多线程执行时如何同步两个子作业?

sql-server - 使用 EF Core 2.1 和 SQL Server 进行正确的并发处理

java - ExecutorService 只运行最近添加的 Callable

ruby-on-rails - 如何部署线程安全的异步 Rails 应用程序?

java - 为什么对于 Thread 的子类来说吞咽 InterruptedException 是可以的?

java - 如何向调用者线程发出 ExecutorService 已完成任务的信号

java - 具有 READ COMMITTED 隔离级别的 SQL 并发 'select then update' 模式