2

辞書クラスを使用して単純なキャッシュを実装しました。

private Dictionary<int, byte[]> cache = new Dictionary<int, byte>();

public void SetPicture(int id, byte[] bytes)
{
    cache[id] = bytes;
}

public byte[] GetPicture(int id)
{
    if (cache.Contains(id)) {
        return cache[id];
    }
    return null;
}

SetPicture は、単一のバックグラウンド スレッドからのみ呼び出されます。(このバックグラウンド スレッドは、Active Directory クエリからユーザー プロファイルの写真を更新しています)。

GetPicture は、他の複数のスレッド (http 要求を処理するスレッド) から呼び出されます。

アイテムがキャッシュから削除されることはありません。

このコードはスレッドセーフですか? または、SetPicture で書き込み中に内部 Dictionary へのアクセスをブロックする必要がありますか?

4

2 に答える 2

6

いいえ、安全ではありません。ディクショナリへのすべてのアクセスを同期する必要があります。ライターに対するリーダーの内容は保証されDictionary<,>ていないためです。また、個別の contains/get チェックは、明らかなスレッド競合です。

オプション:

  • 1.1 スタイルを使用する- 同期なしHashtableで1 つのライター複数の同時リーダーをサポート します (ここでの欠点は、キーが値型であるため、ボックス化する必要があることです。参照型のキーを使用する場合は、より魅力的です。として)intHashtablestring
  • 使うConcurrentDictionary<,>
  • 同期に使用ReaderWriterLockSlim(読み取りは書き込みよりもはるかに一般的であると仮定)
  • 同期に使用lock(重要な書き込みを想定)

でも!Hashtableこのアプローチを使用する場合は、セパレート/取得を行わずContains、インデクサーを使用してください。気がつけばnull無かった。そうしないと、競合状態になります。

于 2012-06-06T07:13:23.680 に答える
2

スレッドセーフではありません。ConcurrentDictionary を使用します。また、エントリが見つからない場合、GetPicture は何かを返す必要があります。

于 2012-06-06T07:14:59.463 に答える