编程语言
首页 > 编程语言> > 使用WeakReference的Java示例的线程安全

使用WeakReference的Java示例的线程安全

作者:互联网

在阅读了SO文章后,我正在阅读Java中的弱引用,并意识到我并不真正知道它们是什么.

以下代码摘自Arnold,Gosling和Holmes撰写的“ Java编程语言,第四版”中的第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” WeakReference的引用.这会创建对引用的强引用,因此,即使在执行空检查之后,在readFile范围之外的所有其他对引用的强引用也会消失(正确的用语是什么?),即使假设该引用不能轻而易举地到达,垃圾回收器也不会允许清除弱引用,从而使引用最终可定型,因为仍然存在来自数据的局部强引用.因此,如果data!= null行中的data不为null,则在下一行返回时,它不能为null.对吗

解决方法:

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

正是出于您所指出的原因,使用弱引用非常有用:代码创建一个强引用,该强引用保存在数据变量中.因此,GC无法收集字节,因此WeakReference将保持不变.因此在单线程应用程序中使用此代码应该是安全的.问题来自多个线程:

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

标签:thread-safety,weak-references,java,garbage-collection
来源: https://codeday.me/bug/20191208/2090224.html