是unmodifiableList线程安全吗?

use*_*587 6 java unmodifiable

我有一个字符串(tagList)列表需要在多个线程之间共享进行读取,所以我创建了一个不可修改的版本并将其传递给线程,我不确定它是否是线程安全的,因为线程只读取该列表所以我猜应该没问题?

当我将该不可修改的列表传递给线程时,它是否传递单个副本并由线程共享,还是创建多个副本并将一个副本传递给每个线程?

这是我的代码:

final List<String> tList = Collections.unmodifiableList(tagList);
List<Future<Void>> calls = new ArrayList<Future<Void>>();

FileStatus[] fsta = _fileSystem.listStatus(p);      
for (FileStatus sta : fsta) {
    final Path path = new Path(sta.getPath(), "data.txt");
    if (!_fileSystem.exists(path)) {        
        continue;
    }
    else {
        calls.add(_exec.submit(new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                filterData(path, tList);
                return null;
            }
        }));
    }
}
Run Code Online (Sandbox Code Playgroud)

Mik*_*rov 7

这完全取决于底层列表在读取操作上是否是线程安全的.修改列表,只是通过了所有读调用,比如size (),get (int)等,以基础列表,无需额外的同步.

想象一下,例如,List的实现缓存哈希码而不是每次需要时计算它.对于这样的实现,hashCode ()方法实际上不是只读的,因为它可以修改内部缓存的哈希码值.

另一个例子是LinkedList的风格,它高速缓存对最后访问的条目及其索引的引用,因此将更快地执行访问附近元素的进一步尝试.对于这样的实现,方法get (int)将不是只读的,因为它更新了缓存的引用和索引,因此可能不是线程安全的.

  • 我不跟随.如果基本的`List`在与正在读取的`unmodifiedList`不同的线程中被修改,那么即使对底层`List`的读操作不引起任何内部修改,也将是多线程访问. (3认同)