当前位置: 首页 > 知识库问答 >
问题:

如何让线程等待ReentantLock被释放?

阳英朗
2023-03-14

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

我一直在研究这个问题,但仍然感到困惑。

请参阅以下通用代码段:

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

我怎么能让线程进入我的其他块等待重入锁被解锁之前继续执行?

共有2个答案

贺俊材
2023-03-14

发布我最终使用的解决方案,以防其他人有类似问题。我选择使用等待通知策略。虽然其他答案很有帮助,但这对我的情况很有效,而且足够简单。

private final ReentrantLock reentrantLock = new ReentrantLock();

public void aCoolMethod(){
    if (reentrantLock.tryLock()){
        try {
            doSomething();
        } finally {
            reentrantLock.unlock();
            synchronized (reentrantLock) {
                reentrantLock.notifyAll();
            }
        }
    } else {
        // have threads wait until reentrantLock is unlocked
        synchronized (reentrantLock) {
            while(reentrantLock.isLocked()) {
                try {
                    reentrantLock.wait();
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }

    doSomethingElse();
}

编辑:发布测试类,以便其他人可以测试此解决方案。只需复制/粘贴并运行它。见下文:

import java.util.concurrent.locks.ReentrantLock;
import java.lang.Thread;

public class LockTest {

    public static void main(String args[]){
        TestClass testClass = new TestClass();

        Thread thread0 = new Thread () {
            public void run () {
                testClass.testLock();
            }
        };
        Thread thread1 = new Thread () {
            public void run () {
                testClass.testLock();
            }
        };
        Thread thread2 = new Thread () {
            public void run () {
                testClass.testLock();
            }
        };

        thread0.start();
        thread1.start();
        thread2.start();

    }

    public static class TestClass{
        ReentrantLock reentrantLock = new ReentrantLock();

        public void testLock(){
            if (reentrantLock.tryLock()) {
                try {
                    System.out.println("Locking");
                    System.out.println(Thread.currentThread().getName() + " will sleep");
                    Thread.sleep(8000);
                    System.out.println(Thread.currentThread().getName() + " has woken up from sleep!!");
                } catch (InterruptedException i) {
                    System.out.println("Interrupted during sleep");
                } finally {
                    System.out.println("Unlocking");
                    reentrantLock.unlock();
                    System.out.println("Notifying");
                    synchronized (reentrantLock) {
                        reentrantLock.notifyAll();
                    }
                }
            } else {
                synchronized (reentrantLock) {
                    while(reentrantLock.isLocked()) {
                        try {
                            System.out.println(Thread.currentThread().getName() + " will wait");
                            reentrantLock.wait();
                            System.out.println(Thread.currentThread().getName() + " has woken up from wait!!");
                        } catch (InterruptedException i) {
                            System.out.println("Interrupted during wait");
                        }
                    }
                }
            }
            System.out.println(Thread.currentThread().getName() + " has reached the end.");
        }

    }

}
章乐逸
2023-03-14

正如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();
}

或者,在没有锁的情况下,您可以使用一致对象来确定哪个线程运行

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();
    }
}
 类似资料:
  • 我打算在主线程中启动2个线程,主线程应该等到所有2个子线程完成,我就是这样做的。 在上面的代码中,确实让主线程等待子线程,但问题是,在第一个线程完成之前不会创建第二个线程。这不是我想要的。 我想要的是,这两个线程立即在主线程中创建,然后主线程等待它们完成。似乎做不到,是吗? 我想,也许我可以通过一个信号灯来完成这项工作,但还有别的方法吗?

  • 我是一个初学者,我正在实施餐饮哲学家的问题。然而,我遇到了一个问题。在我的哲学家()函数中,我希望我的其他线程等待,直到左右筷子都可以使用。我应该如何实现这一点?目前,该计划只是在两位哲学家吃完后终止,而不等待其他人吃完 我已经试过了: 使用互斥锁来锁定哲学家()函数中的共享变量,虽然可以确保没有哲学家挨饿,但使用这种方法意味着放弃并发(即使有筷子可供其他哲学家使用,一次也只能有一位哲学家吃饭)

  • 有时我看到一些线程还没有完成他们的工作,服务杀死那个线程,我怎么能强迫服务等待,直到线程完成他们的工作? 这是我的代码: 我看到了一些例外。future.is完成())块。我怎么能确保每一个未来是当执行者服务关闭?

  • 问题内容: 在这里,我想每秒钟调用一次“ Log.d”和“ postInvalidate”。但是,当我从LogCat检查它时,似乎循环运行的速度比我希望的要快。为什么这个循环不等待1000ms? 以下是LogCat中的输出。因此,您可以看到它根本没有休眠1秒钟。我也使用了Thread.sleep(在您建议之后) 这是最新的代码。是布尔值,现在是事实。 输出是 问题答案: 您需要类的方法。 使发送此

  • 问题内容: 我正在为我的ubuntu服务器(针对我的多客户端匿名聊天程序)实现一种简单的线程池机制,并且需要使我的工作线程进入睡眠状态,直到需要执行一项工作(以函数指针和参数的形式) 。 我当前的系统即将关闭。我(工人线程正在)问经理是否有工作可用,以及是否有5毫秒没有睡眠。如果存在,请将作业添加到工作队列中并运行该函数。糟糕的循环浪费。 什么我 喜欢 做的是做一个简单的事件性的系统。我正在考虑有

  • 问题内容: 我找不到如何测量线程等待锁定的时间。我必须确定一个线程是否正在等待锁定超过1秒,如果需要,则运行另一个线程。谢谢! 问题答案: 试试这个: