java - 使用 Wea​​kReference 的 Java 示例的线程安全

标签 java garbage-collection thread-safety weak-references

在看到一篇 SO 帖子后,我正在阅读 Java 中的弱引用,并意识到我真的不知道它们是什么。

以下代码摘自 Arnold、Gosling 和 Holmes 的“The Java Programming Language, Fourth Edition”中的第 457 页,第 17 章“垃圾收集和内存”

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”弱引用的引用。这会创建对引用对象的强引用,因此即使在空检查之后,readFile 范围之外的所有其他对引用对象的强引用都会消失(正确的术语是什么?),即使假设引用对象不可软访问,垃圾收集器也不会允许清除弱引用,从而使引用对象可终结,因为数据中仍然存在对它的本地强引用。因此,如果 data != null 行中的数据不为 null,则在下一行返回时它不能为 null。正确吗?

最佳答案

我认为示例代码不是线程安全的,但出于与使用弱引用不同的原因:

弱引用的用法很好,完全符合您指出的原因:代码创建了一个强引用,该引用保存在 data 变量中。因此,GC 无法收集字节,因此 WeakReference 也将保持完整;因此在单线程应用程序中使用此代码应该是安全的。问题来自多线程:

filelastData 字段的访问是同步的,因此不能保证两个线程与 一起工作readFile(..) 方法完全交互(这将是不太可能的“最佳”情况)。重要的是要注意,必须以原子方式访问这些字段,如果没有其他地方接触到它们,最简单的解决方法是将 readFile 方法声明为同步的。这会严重损害性能,因为文件读取将发生在同步块(synchronized block)内,可能导致不良争用。

关于java - 使用 Wea​​kReference 的 Java 示例的线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6383013/

相关文章:

java - 是否有用于调度依赖可运行对象的 Java 库(在依赖 DAG 中给出)?

java - 使用反射调用带有数组参数的方法

java - Reflect 是否能够加载外部类/jar 作为插件

没有引用对象时的 Java 垃圾回收

garbage-collection - 是否-XX :+CMSIncrementalMode run on application threads or in GC-dedicated threads?

java - ServletContext#getRealPath(File.separator) 在 tomcat 中给出 null

c# - 在这种情况下如何减少垃圾产生

Python 3 "Lock"为 : threads and processes

thread-safety - Lock.protect和callame

java - 将读取同步到 java 集合