跟踪Java中的引用

时间:2015-04-29 09:38:12

标签: java multithreading reference

在Java中,有没有办法判断引用是否正在维护到其他线程(或一般)中的对象?

考虑以下课程:

public class ResourcePool<TYPE>
{
    private final Queue<Object> emptyLocks = new LinkedBlockingQueue<>();

    private final Queue<TYPE> available = new LinkedBlockingQueue<>();
    private final Queue<TYPE> claimed = new LinkedBlockingQueue<>();

    public void add(TYPE resource)
    {
        available.add(resource);
    }

    public TYPE claim() throws InterruptedException
    {
        if (available.isEmpty())
        {
            Object lock = new Object();
            synchronized (lock)
            {
                emptyLocks.add(lock);
                lock.wait();
            }
        }

        TYPE resource = available.poll();
        claimed.add(resource);
        return resource;
    }

    public void release(TYPE resource)
    {
        if (!claimed.remove(resource)) return;
        available.add(resource);

        Object lock = emptyLocks.poll();
        if (lock != null) synchronized (lock) {lock.notify();}
    }
}

这里的想法是多个线程可以声明/释放资源,这样两个线程在任何给定时刻都不会拥有相同的资源。但是如果一个线程忘记释放()一个资源会发生什么?更糟糕的是,如果线程调用release()然后继续使用资源做什么怎么办?

使用WeakReference类,可以判断何时不存在对给定对象的更强引用。然而,当发生这种情况时,该对象被垃圾收集并且它已经消失。 SoftReference可能会起作用,但在我们将资源重新放入&#34;可用&#34;之前,我们的资源仍然可能是GC。列表。

所以问题是:有没有办法跟踪这些资源是否仍然在使用?

理想情况下,线程可以声明()资源,只要他们想要使用它们,并且只要不再维护引用就会自动释放这些资源。我认为这将非常优雅,并且在其他情况下也很有用。

1 个答案:

答案 0 :(得分:1)

答案很简单:没有

GC在VM全局级别和当前实现(至少在Hotspot中)工作,它不使用引用计数,更不用于参考跟踪。这意味着即使VM也不总是知道在任意时间点引用的是什么。

GC通常也是用于跟踪需要及时发布的内容的错误工具; GC可能很少运行(在极端情况下,GC可能会调整为每隔小时运行一次)。一旦拥有块范围结束,您可能希望您的资源可用于其他线程;要求与GC的松散处理大不相同。

你想要的是立即检测每个线程超出范围的事物。虽然这是一个很好的功能,但问题是它是否值得对其产生的性能影响。

您的资源示例和一个“忘记”在发布后释放/保留资源的线程是可以通过约定处理的事情:使用try-finally或者滥用try-with-resources块来确保生命周期得到妥善维护。

为了捕获资源的意外泄漏,您可以滥用最终结果;但是当资源最终确定时,它不能预测(并且你只能进行清理,不应该完成恢复资源;请参阅JLS关于最终确定)。

编辑:通过在资源中占用所有者,您可以在发布后使用资源轻松地防御对抗胭脂线程。然后,资源可以执行运行时检查调用线程确实是当前所有者。