java锁可以在锁定时进行垃圾收集吗?
锁(java.util.concurrent.Locks.Lock)是否可以在锁定时进行垃圾收集? 假设一个纯理论的例子:
WeakReference r;
public void foo(){
Lock lock = new ReentrantLock();
r = new WeakReference(lock);
lock.lock();
}
在执行foo()
之后lock
是否可以被垃圾收集?换句话说,lock.lock()
是否创建任何强引用返回锁?
你怎么知道的
# 1 楼答案
当锁定的
Lock
不再可访问时,可以对其进行垃圾回收。(JLS中“可访问”的定义是:“可访问对象是可以从任何活动线程在任何潜在的连续计算中访问的任何对象。”-JLS 12.16.1)但是,某个线程正在等待的被锁定的
Lock
必须执行锁的Lock/tryLock实例方法之一。要实现这一点,线程必须具有对锁的引用;i、 e.锁定方法当前正在访问的对象。因此,某个线程试图获取的锁定锁是可访问的,不能被垃圾回收否。在您的示例中,强引用以
lock
变量的形式存在。但是假设我们调整了您的示例以除去lock
;e、 g调用
get()
时,它将返回对ReentrantLock
对象的引用,该对象将保存在临时变量或寄存器中,从而使其具有强可访问性。只要lock()
调用正在运行,它将继续是强可访问的。当lock()
调用返回时,ReentrantLock
对象可能变得弱可及(再次)我怎么知道?以下各项的组合:
不需要使用全局队列实现
Lock
,因此没有理由对Lock
对象进行隐藏引用,以防止它变得不可访问。此外,当一个Lock
被锁定时无法进行垃圾收集,这将是一个存储泄漏,也是一个主要的实现缺陷,我无法想象Doug Lea等人会犯这样的错误# 2 楼答案
假设你的意思是“在
foo()
被执行之后”,答案是肯定的——这确实是weakreference的重点您应该知道,因为当您尝试将}转换回常规(或强)引用时,会返回
WeakReference
{null
:# 3 楼答案
从技术上讲,唯一不能被垃圾收集的对象是引导类加载器加载的类(其余的是对前者的传出引用)
(java.util.concurrent.locks)锁是绝对正常的对象,与java没有区别。util。ArrayList在垃圾收集方面的作用。我已经编写了带有后进先出语义的锁(或者特别是非FIFO的锁),这对于最小化缓存未命中非常有用,因为最热的线程可以工作得更多。关键是,完全可以编写自己的自定义锁定/同步/原子代码
# 4 楼答案
事实证明,虽然我们通常在概念上认为线程“获取”和“拥有”锁,但从实现的角度来看,事实并非如此。锁保留对拥有和等待线程的引用,而线程没有对锁的引用,也不知道它们“拥有”的锁
ReentrantLock实现也相当简单:没有静态锁集合,也没有跟踪锁的后台维护线程
创建或锁定锁都不会在任何地方创建任何“隐藏”的新强引用,因此,在上面的示例中,
lock
一旦完成foo()
就可以进行垃圾收集可以通过仔细阅读源代码来验证这一点:
http://fuseyism.com/classpath/doc/java/util/concurrent/locks/ReentrantLock-source.html
http://fuseyism.com/classpath/doc/java/util/concurrent/locks/AbstractQueuedSynchronizer-source.html
http://fuseyism.com/classpath/doc/java/util/concurrent/locks/AbstractOwnableSynchronizer-source.html
# 5 楼答案
它可以在锁定时进行垃圾收集。获取锁不会创建强引用。当然,正如所写的,您必须将lock设置为null并运行gc以查看引用变为null
# 6 楼答案
锁与任何其他对象都不一样。这取决于内部Java机制是否引用了锁。但是我看不出Java为什么要保留对锁的引用