是否可以保证在线程持有监视器时对象不会被垃圾回收?
例如
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();
}
}
具体来说,在这种情况下,如果在调用另一个线程时调用 thread2()
,是否可以保证 b
将是非 null
在 thread1()
中 sleep ?我们假设整个 thread2()
被执行,而 thread1()
正在另一个线程中 hibernate 。
最佳答案
同步可以防止垃圾回收,但不是一般情况。在您的具体情况下,我们无法保证。
与 JLS §12.6.1 比较
…
Transformations of this sort may result in invocations of the
finalize
method occurring earlier than might be otherwise expected. In order to allow the user to prevent this, we enforce the notion that synchronization may keep the object alive. If an object's finalizer can result in synchronization on that object, then that object must be alive and considered reachable whenever a lock is held on it.Note that this does not prevent synchronization elimination: synchronization only keeps an object alive if a finalizer might synchronize on it. Since the finalizer occurs in another thread, in many cases the synchronization could not be removed anyway.
因此,由于您的对象没有自定义终结器,因此在终结期间可能不会发生同步,原则上,您的对象是一个允许消除锁的临时对象,在这种情况下它不会阻止垃圾回收。
但是存在一个实际障碍,即您存储 WeakReference
的方式使得另一个线程可以在未收集对象时检索该对象,一旦存在这种可能性,该对象就不再是本地对象并锁定不能应用消除。
在构建之后立即积极收集对象(或完全消除它的存在)并在它逃逸之前清除弱引用或首先创建一个空的 WeakReference
的理论实现将在规范,因为在该执行场景中,锁消除是合理的。
请注意,即使您插入 reachabilityFence
, 在调用 thread1()
的线程和调用 thread2()
的线程之间没有 happens-before 关系,因此第二个线程可能总是表现得好像在执行 thread2()
在另一个完成 synchronized
block 或通过可达性栅栏之后,即使您的现实生活时钟另有说明。这是said explicitly Thread.sleep
没有同步语义。
关于java - Java 是否保证当前同步的对象不会被垃圾回收?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57872699/