Dahili olarak senkronize etmeye çalışmak neredeyse kesinlikle yetersiz olacaktır çünkü çok düşük bir soyutlama seviyesinde. Add
Ve ContainsKey
işlemlerini ayrı ayrı aşağıdaki gibi iş parçacığı açısından güvenli hale getirdiğinizi varsayalım:
public void Add(TKey key, TValue value)
{
lock (this.syncRoot)
{
this.innerDictionary.Add(key, value);
}
}
public bool ContainsKey(TKey key)
{
lock (this.syncRoot)
{
return this.innerDictionary.ContainsKey(key);
}
}
O halde bu sözde iş parçacığı güvenli bit kod parçasını birden çok iş parçacığından çağırdığınızda ne olur? Her zaman iyi çalışır mı?
if (!mySafeDictionary.ContainsKey(someKey))
{
mySafeDictionary.Add(someKey, someValue);
}
Basit cevap hayır. Bir noktada, Add
yöntem, anahtarın sözlükte zaten mevcut olduğunu belirten bir istisna atacaktır. İş parçacığı açısından güvenli bir sözlükle bu nasıl olabilir, sorabilirsiniz? Her işlemin iş parçacığı açısından güvenli olması nedeniyle, iki işlemin birleşimi değildir, çünkü başka bir iş parçacığı çağrınız ContainsKey
veAdd
.
Bu, bu tür bir senaryoyu doğru yazmak için sözlüğün dışında bir kilide ihtiyacınız olduğu anlamına gelir , örn.
lock (mySafeDictionary)
{
if (!mySafeDictionary.ContainsKey(someKey))
{
mySafeDictionary.Add(someKey, someValue);
}
}
Ama şimdi, harici olarak kilitleme kodu yazmak zorunda olduğunuza göre, dahili ve harici senkronizasyonu karıştırıyorsunuz, bu da her zaman net olmayan kod ve kilitlenme gibi sorunlara yol açıyor. Yani sonuçta muhtemelen şunlardan birini yapmak daha iyidir:
Bir normal kullanın Dictionary<TKey, TValue>
ve üzerinde bileşik işlemleri içeren harici olarak senkronize edin veya
Yöntem IDictionary<T>
gibi işlemleri birleştiren farklı bir arabirime (yani değil ) sahip yeni bir iş parçacığı güvenli sarmalayıcı yazın, AddIfNotContained
böylece ondan işlemleri birleştirmenize asla gerek kalmaz.
(Ben 1 numara ile gitme eğilimindeyim)