簡體   English   中英

鎖可以鎖定垃圾嗎?

[英]Can Locks be garbage collected while locked?

鎖定時可以鎖定垃圾(java.util.concurrent.locks.Lock)嗎? 假設一個純理論的例子:

WeakReference r;

public void foo(){
       Lock lock = new ReentrantLock();
       r = new WeakReference(lock);   
       lock.lock();
}

foo()執行后, lock可以被垃圾收集? 換句話說, lock.lock()創建lock.lock()引用回鎖? 你怎么知道的?

當鎖定的Lock無法再訪問時,可以對其進行垃圾回收。 (JLS中“可達”的定義是: “可達對象是任何可以從任何活動線程繼續計算中訪問的對象。” - JLS 12.16.1)

但是, 某個線程正在等待的鎖定Lock必須執行Lock的lock / tryLock實例方法之一。 為此,線程必須具有對鎖的引用; 即鎖定方法當前正在訪問的一個。 因此,某些線程試圖獲取的鎖定鎖是可達的,並且不能被垃圾收集。

換句話說,lock.lock()是否會創建任何強引用回鎖?

在您的示例中,強引用以lock變量的形式存在。 但是假設我們調整了你的例子以擺脫lock ; 例如

public void do_lock(WeakReference<ReentrantLock> r) 
   r.get().lock();
}

當你調用get() ,它將返回對ReentrantLock對象的引用,該對象將保存在臨時變量或寄存器中,使其可以很容易地訪問。 只要lock()調用正在運行,它將繼續強烈可達。 lock()調用返回時, ReentrantLock對象可能會再次變弱(可再次)。

你怎么知道的?

我怎么知道? 結合:

  • 了解Java語言規范對可達性和其他事物的定義,
  • 實現JVM的經驗,
  • 良好的老式邏輯,......
  • 我通過閱讀OpenJDK源代碼確認了這一點(盡管這並不能證明 JVM的一般性。)

不需要使用全局隊列來實現Lock ,因此沒有理由對Lock對象進行隱藏引用,以防止它無法訪問。 此外, Lock無法進行垃圾收集將成為存儲泄漏,並且是一個主要的實現缺陷,我無法想象 Doug Lea等人犯了這個錯誤!

事實證明,雖然我們通常在概念上認為線程“獲得”和“擁有”鎖,但實際上並非從實現角度來看。 鎖保持對擁有和等待線程的引用,而線程沒有對鎖的引用,並且不知道它們擁有的鎖。

ReentrantLock實現也相當簡單:沒有靜態的鎖集合,並且沒有跟蹤鎖的后台維護線程。

創建或鎖定鎖都不會在任何地方創建任何“隱藏的”新強引用,因此,在上面的示例中,一旦foo()完成,就可以對lock進行垃圾收集。

可以通過仔細閱讀源代碼來驗證這一點:

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

從技術上講,唯一不能被垃圾收集的對象是bootstrap類加載器加載的類(其余是對前者的傳出引用)

(java.util.concurrent.locks。)Lock(s)絕對是普通的對象,在垃圾收集方面與java.util.ArrayList沒有什么不同。 我已經編寫了具有LIFO語義的鎖(或者特別是不是FIFO的AbstractQueueSynchronized),這對於最小化緩存未命中非常有用,因為最熱門的線程可以開始工作。 點是絕對可以編寫自己的自定義鎖定/同步/原子代碼。

假設你的意思是“在執行foo()之后”,答案是肯定的 - 這確實是WeakReferences的重點。

你會知道,因為當你試圖將轉換WeakReference r回一個正常的(或強)引用,你會得到null返回:

if (r.get() == null) {
    // the lock was garbage collected
}

Lock與任何其他對象都沒有什么不同。 這取決於某些內部Java機制是否引用了Lock。 但我認為Java沒有理由保留對Lock的引用。

它可以在鎖定時進行垃圾收集。 通過鎖定不會創建強引用。 當然,在編寫時,您必須將lock設置為null並運行gc以查看引用為null。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM