1

の助けを借りて IO をキャッシュしたいと思いConcurrentHashMapます。バイナリ ファイルの変更は、キャッシュにも反映されるはずです。キャッシュは複数のスレッドで使用されるため、すべての IO 操作が同期されます。マップの変更は同じsynchronizedブロック内に入ります。大まかに次のようになります。

synchronized (file) {
    file.deleteRecord(index)
    map.remove(index);
}

synchronized(file) {
    file.writeRecord(index, record);
    map.put(index, record);
}

mapとはどちらfileも非公開であり、キャッシュ クラスの外部からは見えません。

キャッシュ読み取り、つまりブロックmap.get(index)なしで行った場合、スレッドセーフは保持されますか?synchronized

前述したように、ConcurrentHashMapマップの実装として使用されます。

4

4 に答える 4

5

うん。これが基本的にポイントですConcurrentHashMapドキュメントから:

通常、取得操作 (get を含む) はブロックされないため、更新操作 (put および remove を含む) と重複する場合があります。検索は、 開始時に保持されている最新の更新操作の結果を反映します。

およびパッケージのドキュメントから:

並行コレクションはスレッドセーフですが、単一の排他ロックによって制御されません。の特定のケースではConcurrentHashMap、任意の数の同時読み取りと、調整可能な数の同時書き込みを安全に許可します。

(もちろん、どちらのドキュメント ページにも詳細が記載されています。注意深く読む価値があります。)

于 2009-07-05T18:31:40.380 に答える
2

はい、ConcurrentHashMap 実装のおかげで、マップ参照までスレッド セーフが維持されます。

マップに格納するオブジェクトは別の話です。

于 2009-07-05T18:33:21.080 に答える
1

はい、ConcurrentHashMap はスレッド セーフであるため、読み取り (または書き込み) でロックを行う必要はありません。

ただし、この例では、次の一連のイベントが発生する可能性があります。

file.deleteRecord(index);
map.get(index) // returns the mapping for index even though it has been deleted from file
map.remove(index);

(writeRecord/put も同様)。これは、あなたのケースでは問題になる場合とそうでない場合があります。

于 2009-07-06T23:42:20.183 に答える
0

ここにいる誰もが言うように、これはキャッシュへの書き込みとキャッシュからの読み取りの間に事前発生関係があるという点でスレッドセーフですが、他に何を保証するかによっては意味がない場合があります。

たとえば、ファイルを fsync しない限り、レコードがディスクに書き込まれる保証はないため、ディスクからレコードを読み取ることはできません (ファイル システムやその他のいくつかの要因によって異なります)。また、writeRecord/deleteRecord とマップの書き込みとマップからの読み取りの間には、事前発生の関係がないため、JMM は、確実にファイルに書き込まれたマップから何かを読み取ることを保証しません。

index書き込まれたandrecordオブジェクトの状態が読み取られるものになるという保証が得られますが、これらのいずれかが可変である場合、それはかなり役に立たない保証になる可能性があります。

于 2011-01-05T23:36:47.390 に答える