Java并发 - 监视器是否被阻止?

时间:2013-07-25 13:30:14

标签: java multithreading synchronization

如果另一个线程在同一个监视器上阻塞 / 等待,是否可以从一个线程(比如锁定监视器对象的线程)判断?

示例场景 -

  

“收集器”线程从共享对象读取数据,而   “updater”线程可能被阻塞并等待收集   结束。我希望收藏家知道他什么时候结束   收集,可能的数据更新正在等待产生   收集的数据可能已经无效。

在我的情况下,收集可能是一项耗时的操作,而且在下一阶段,“收集器”线程会分析数据一段时间,这在数据无效的许多情况下可能是冗余操作。

3 个答案:

答案 0 :(得分:3)

  

如果另一个线程在同一个监视器上阻塞/等待,是否有办法从一个线程(比如锁定监视器对象的线程)判断?

不,不是来自对象本身。正如@Evgeniy所提到的,您可以使用其他允许您查看排队成员的java.util.concurrent.locks.*类,但不能使用synchronized (lock)类型的对象监视器。

  

我希望收集者知道,当他完成收集时,可能的数据更新正在等待,这会导致收集的数据可能已经无效。

如何进行BlockingQueue更新,以便收集器可以检查队列并查看它是否为非空。更新程序线程只是将Update信息添加到BlockingQueue,收集器会使更新出列并进行调整。然后,它可以检查队列的长度,并决定是否需要进入分析模式。

private BlockingQueue<Update> updateQueue = new LinkedBlockingQueue<Update>();
...
// called by the updater thread(s)
public void updateData(Update update) {
    updateQueue.put(update);
}
// called by the collector
public void collect() {
    while (!Thread.currentThread().isInterrupted()) {
        Update update = updateQueue.take();
        updateValues(update);
        if (updateQueue.isEmpty()) {
           analyzeData();
        }
    }
}

无论您如何操作,您都需要使用其他机制来考虑新数据更新,而不是检查所有线程的阻塞状态。

答案 1 :(得分:3)

如果您使用java.util.concurrent.locks框架,可以获取此信息,ReentrantLock类具有以下方法:

Collection<Thread> getQueuedThreads() - 返回包含可能正在等待获取此锁的线程的集合

Collection<Thread> getWaitingThreads(Condition condition) - 返回一个集合,其中包含可能正在等待与此锁定关联的给定条件的那些线程。

答案 2 :(得分:0)

一个基本解决方案:添加二进制标志和另一个监视器对象:

volatile boolean  haveUpdate = false;
final Object      updateMonitor = new Object();

当更新程序线程有新更新时,将haveUpdate设置为 true ,然后再在数据监视器上进行同步。在数据同步块中的任何位置将其设置回 false (它是唯一可以访问数据的线程)。

收集线程可以定期检查值,如果 true 则中断。当收集线程中断时,它们应该调用updateMonitor.wait(),然后循环返回再次收集。当更新程序线程离开数据同步块时,它应该调用updateMonitor.notifyAll()

现在,当任何收集线程看到有正在进行或正在进行的更新时,它将停止,等待它完成,然后再次启动。