データベース内のテーブルに値を挿入して ID を取得するいくつかの非常に中心的な関数にキャッシュ レイヤーを導入することで、データベース サーバーから作業をオフロードしようとしています。これはマルチスレッド環境にあります。
私の最初のアプローチは次のとおりです。
public class Cache {
private Dictionary<string, Int64> i;
public void Init() { /* init i with values from DB */ }
public Int64 Get(string value)
lock(i) {
Int64 id;
if (cache.i.TryGetValue(value, out id))
return id;
id = /* Insert to DB and retrieve ID */
cache.i[value] = id;
return id;
}
}
これは役に立ちました。ただし、スレッドはまだお互いに多くのことを待ちます。この待ち時間を減らしたい。私の最初の考えは、を使用することConcurrentDictionary.GetOrAdd(key, valueFactory)
でした。valueFactory が複数回呼び出される可能性があるため、これは機能しません。
私はこのアプローチに行き着きました:
public class Cache
{
private ConcurrentDictionary<string, Int64> i;
public void Init() { /* init i with values from DB */ }
public Int64 Get(string value)
{
Int64 id;
if (i.TryGetValue(value, out id))
return id;
lock (i)
{
if (i.TryGetValue(value, out id))
return id;
id = /* Insert to DB and retrieve ID */
i.TryAdd(value, id);
return id;
}
}
これを行うより良い方法はありますか?これもスレッドセーフですか?