当线程持有其监视器时,是否可以保证对象不会被垃圾收集?
e.g.
class x {
private WeakReference<Object> r;
Object getMonitorObject() {
Object o = new Object();
r = new WeakReference<>(o);
return o;
}
void thread1() throws Exception {
synchronized (getMonitorObject()) {
Thread.sleep(3000);
}
}
void thread2() {
Object b = r.get();
}
}
具体来说,在这种情况下,是否有任何保证b
将是非null
if thread2()
当另一个线程正在休眠时被调用thread1()
?我们假设整个thread2()
执行时thread1()
正在睡觉在不同的线程中。
同步可以防止垃圾收集,但一般情况下不会。对于您的具体情况,我们无法保证。
与之比较JLS§12.6.1 https://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.6.1
…
这种类型的转换可能会导致调用finalize
方法发生的时间早于预期。为了允许用户防止这种情况,我们强制执行同步可以使对象保持活动状态的概念。如果一个对象的终结器可以导致该对象上的同步,则该对象必须处于活动状态,并且只要在其上持有锁,该对象就必须被视为可访问。
请注意,这不会阻止同步消除:同步仅在终结器可能对其进行同步时才使对象保持活动状态。由于终结器发生在另一个线程中,因此在许多情况下无论如何都无法删除同步。
因此,由于您的对象没有自定义终结器,因此在终结过程中可能不会发生同步,原则上,您的对象是一个允许消除锁的临时对象,在这种情况下,它不会阻止垃圾收集。
但存在一个实际障碍,即您存储了WeakReference
在某种程度上,另一个线程可以在未收集对象时检索该对象,一旦存在这种可能性,该对象就不再是本地的,并且无法应用锁消除。
一种理论上的实现,在构造后立即积极地收集对象(或完全消除其存在)并在弱引用逃逸或创建空之前清除弱引用WeakReference
首先,将在规范范围内,因为在该执行场景中,锁消除是合理的。
请注意,即使您插入reachabilityFence https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ref/Reference.html#reachabilityFence(java.lang.Object),线程调用之间不存在happens-before关系thread1()
和另一个电话thread2()
,所以第二个线程可能总是表现得好像正在执行thread2()
对方完成后synchronized
阻止或通过可达围栏,即使您现实生活中的时钟另有说明。它是明确表示 https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.3 that Thread.sleep
没有同步语义。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)