2011-06-17 57 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