マルチスレッドアプリケーションで使用するコンカレントディクショナリにクラスのインスタンスをキャッシュする次のコードがあります。
簡単に言うと、id パラメーターを使用してクラスをインスタンス化すると、まず、指定された id を持つ privateclass のインスタンスが辞書に存在するかどうかがチェックされ、存在しない場合は privateclass のインスタンスが作成されます (これには長い時間がかかり、場合によっては数秒かかります)。将来の使用のために辞書に追加します。
public class SomeClass
{
private static readonly ConcurrentDictionary<int, PrivateClass> SomeClasses =
new ConcurrentDictionary<int, PrivateClass>();
private readonly PrivateClass _privateClass;
public SomeClass(int cachedInstanceId)
{
if (!SomeClasses.TryGetValue(cachedInstanceId, out _privateClass))
{
_privateClass = new PrivateClass(); // This takes long time
SomeClasses.TryAdd(cachedInstanceId, _privateClass);
}
}
public int SomeCalculationResult()
{
return _privateClass.CalculateSomething();
}
private class PrivateClass
{
internal PrivateClass()
{
// this takes long time
}
internal int CalculateSomething()
{
// Calculates and returns something
}
}
}
私の質問は、このコードをスレッド セーフにするために、外部クラス コンストラクターの生成と割り当ての部分にロックを追加する必要がありますか、それともそのままでよいのでしょうか?
アップデート:
SLaks さんの提案の後、 ConcurrentDictionary のGetOrAdd()メソッドをLazyの組み合わせで使用しようとしましたが、残念ながらコンストラクターがPrivateClass
複数回呼び出されました。テスト コードについては、https://gist.github.com/3500955を参照してください。
更新 2: ここで最終的な解決策を確認できます: https://gist.github.com/3501446