動的コンテンツがたくさんあるASP.NETアプリケーションがあります。内容は、特定のクライアントに属するすべてのユーザーで同じです。リクエストごとに必要なデータベースヒットの数を減らすために、クライアントレベルのデータをキャッシュすることにしました。データを保持する静的クラス( "ClientCache")を作成しました。
このクラスで最もよく使用されるメソッドは「GetClientData」です。これは、特定のクライアントに保存されているすべてのデータを含むClientDataオブジェクトを返します。ただし、ClientDataは遅延してロードされます。要求されたクライアントデータがすでにキャッシュされている場合、呼び出し元はキャッシュされたデータを取得します。それ以外の場合は、データがフェッチされ、キャッシュに追加されてから、呼び出し元に返されます。
最終的に、ClientDataオブジェクトがキャッシュに追加された行のGetClientDataメソッドで断続的なクラッシュが発生し始めました。メソッド本体は次のとおりです。
public static ClientData GetClientData(Guid fk_client)
{
if (_clients == null)
_clients = new Dictionary<Guid, ClientData>();
ClientData client;
if (_clients.ContainsKey(fk_client))
{
client = _clients[fk_client];
}
else
{
client = new ClientData(fk_client);
_clients.Add(fk_client, client);
}
return client;
}
例外テキストは常に「同じキーを持つオブジェクトがすでに存在します」のようなものです。もちろん、クライアントがすでに存在する場合は、クライアントをキャッシュに追加できないようにコードを記述しようとしました。
この時点で、競合状態が発生し、メソッドが2回同時に実行されている可能性があります。これにより、コードがどのようにクラッシュするかを説明できます。しかし、私が混乱しているのは、メソッドを2回同時に実行する方法です。私の知る限り、ASP.NETアプリケーションは一度に1つの要求しか処理しません(そのため、HttpContext.Currentを使用できます)。
それで、このバグは、クリティカルセクションにロックをかける必要がある競合状態である可能性がありますか?それとも私はもっと明白なバグを見逃していますか?