8

読み取りのために複数のスレッド間で共有する必要がある文字列(tagList)のリストがあるので、変更不可能なバージョンを作成してスレッドに渡します。スレッドはそのリストのみを読み取るため、スレッドセーフかどうかはわかりません。それは大丈夫ですか?

また、その変更不可能なリストをスレッドに渡すと、単一のコピーを渡してスレッドで共有しますか、それとも複数のコピーを作成して各スレッドに 1 つのコピーを渡しますか?

ここに私のコードがあります:

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;
            }
        }));
    }
}
4

3 に答える 3

9

これは、基になるリストが読み取り操作でスレッドセーフであるかどうかに完全に依存します。変更不可能なリストは、追加の同期なしで、などのすべての読み取り呼び出しを基礎となるリストsize ()に渡すだけです。get (int)

たとえば、必要になるたびにハッシュコードを計算するのではなく、ハッシュコードをキャッシュする List の実装を想像してみてください。このような実装でhashCode ()は、内部的にキャッシュされたハッシュ コード値を変更する可能性があるため、メソッドは実際には読み取り専用ではありません。

もう 1 つの例は、最後にアクセスされたエントリへの参照をそのインデックスとともにキャッシュする LinkedList のフレーバーです。そのため、近くの要素へのアクセスをさらに試みると、はるかに高速に実行されます。このような実装では、get (int)キャッシュされた参照とインデックスを更新するため、メソッドは読み取り専用ではなく、おそらくスレッド セーフではありません。

于 2013-02-05T18:01:17.657 に答える
2

これはスレッドセーフです (変更できないため)。同じコピーを渡します。

ただし、ラップされた List ( tagList) はまだスレッドセーフではありません。共有されている間は、ラップされたリストを変更してはなりません。によって返されるリストunmodifiableList()が安全である唯一の理由は、ラップされたリストへの変更が許可されていないためです。

于 2013-02-05T18:00:19.890 に答える
0

あなたが言うように、リストは変更できません。したがって、スレッドセーフになります。

オブジェクトを渡すとき、実際にはオブジェクトへの参照を渡します (実際のオブジェクトではありません)。単一のコピーがあり、変更されていないため、スレッドセーフのままです。

1 つだけ注意してくださいtagListに直接アクセスしないでください。tListという名前のラップされた変更不可能なコレクションを介して常にアクセスします。これは、適切にカプセル化すれば実現できます。

于 2013-02-05T18:03:32.863 に答える