2011-06-17 54 views
3

我正在閱讀Java中的弱引用後,找到一個SO帖子,並意識到我真的不知道他們是什麼。使用WeakReference的Java示例的線程安全

下面的代碼是從第457,第17章:在「Java編程語言,第四版」由阿諾德·高斯林和霍姆斯

import java.lang.ref.*; 
import java.io.File; 

class DataHandler { 
    private File lastFile;  // last file read 
    private WeakReference<byte[]> 
         lastData;// last data (maybe) 

    byte[] readFile(File file) { 
     byte[] data; 

     // check to see if we remember the data 
     if file.equals(lastFile) { 
      data = lastData.get(); 
      if (data != null) 
       return data; 
     } 

     // don't remember it, read it in 
     data = readBytesFromFile(file); 
     lastFile = file; 
     lastData= new WeakReference<byte[]>(data); 
     return data; 
    } 
} 

我想了解「垃圾收集和內存」 ,只是爲了鍛鍊,如果這個代碼是線程安全的,與我專注於作爲線

data = lastData.get(); 
if (data != null) 
    return data; 

我的想法是如下的代碼部分:「數據」線程限制並且設置爲引用「lastData」WeakReference的引用。這爲參照物創建了一個強有力的參考,因此即使在空檢查之後,對readFile範圍之外的參照物的所有其他強引用都消失了(什麼是正確的術語?),並且即使假設參照物不是輕度可達的,垃圾收集器也不是允許清除弱引用,從而使所指對象可終結,因爲仍然有來自數據的本地強引用。因此,如果data != null行中的數據不爲空,則在下一行中返回時不能爲空。正確嗎?

回答

2

我想示例代碼是線程安全的,但出於不同的原因不是使用弱引用:

弱引用的使用是好的,正是爲你指出的理由:該代碼創建在data變量中保存的強烈參考。因此,GC無法收集字節,因此WeakReference也會保持不變;所以在單線程應用程序中使用此代碼應該是安全的。這些問題都與多線程:

filelastData領域的訪問是同步的,因此不存在保證與readFile(..)方法交互工作的兩個線程在所有(這是不太可能的「最佳」案件)。需要注意的是,必須以原子方式訪問這些字段,並且如果沒有其他地方觸及它們,則最簡單的解決方法是聲明readFile方法同步。這會嚴重影響性能,因爲文件讀取會在同步塊內發生,可能會導致較差的爭用。

+1

而不是同步,我會做一個類,保存文件和數據作爲最終變量。然後對該類進行易變的引用。然後readFile可以獲得對該類引用的本地引用,並通過該方法使用它。然後在完成時更新實例字段。 – 2011-06-17 15:18:42

+0

@Michael你是對的,那絕對是一種方式。我只想指出實現它的最簡單方法。 – Waldheinz 2011-06-17 22:28:13

2

一旦引用已分配給本地data變量,則該對象不符合垃圾回收的條件。它是strongly reachable,因爲在線程的堆棧中有對它的引用。

+0

謝謝。我想我會把這兩條線過於複雜。只是注意到對數據的強烈引用就足夠了。關於強烈可達性:它表明有兩個定義在使用。你引用的一個:「如果某個線程可以在不經過任何引用對象的情況下到達某個對象,則該對象是可以被強制訪問的。」其次從Java規範:「可訪問的對象是任何可以從任何活動線程進行任何潛在的持續計算中訪問的對象」這些是否相等,是否存在第二個語義嚴格定義的地方?我覺得規範並不總是精確的 – adderley 2011-06-17 12:33:09

-1

從技術上講,它不是線程安全的,因爲lastData和lastFile不是易失性的。第二個線程可能會看到這些引用的舊副本。它對你的應用程序可能沒有太大的區別。

+1

我曾經假設線程的討論進入它純粹是因爲垃圾收集和'readFile'不是跨線程調用。你當然是對的。 – McDowell 2011-06-17 08:18:56

+0

我想補充一點,使字段易失性也無濟於事,因爲它會允許文件<->數據關聯不同步,因此可能會返回錯誤的數據,因爲文件字段已經更新,而引用不是。 – Waldheinz 2011-06-17 08:27:47