私がこの関数を持っているとしましょう(スレッドセーフな方法でキャッシュにアクセスしていると仮定します):
object GetCachedValue(string id)
{
if (!Cache.ContainsKey(id))
{
//long running operation to fetch the value for id
object value = GetTheValueForId(id);
Cache.Add(id, value);
}
return Cache[id];
}
2つのスレッドが同じ値で同時に「長時間実行操作」を実行しないようにしたい。もちろん、すべてをlock()でラップすることはできますが、値に関係なく関数全体がブロックされるため、2つのスレッドが異なるIDを探している限り、長時間実行される操作を実行できるようにする必要があります。
値に基づいてロックする組み込みのロックメカニズムがあり、一方のスレッドがブロックでき、もう一方のスレッドが長時間実行操作を完了して、2回(またはN回)実行する必要がありませんか?理想的には、長時間実行される操作が1つのスレッドで実行されている限り、他のスレッドが同じID値に対してそれを実行できないようにする必要があります。
IDをHashSetに入れ、操作が完了したら削除することで自分自身をロールバックできますが、それはハックのようです。