Bir uygulamada, gerçek zamanlı olarak güncellenen olması gereken etki alanı nesneleri koleksiyonu var. Birkaç iş parçacığı, bu koleksiyonda bulunan 'daki öğeleri değiştiren bir işlem yapabilir ve bunu güvenle yapmalıdır. Şu anki yaklaşım, herhangi bir değişiklik yapmadan önce esas olarak küresel bir kilit alan, basitliğidir. Aşağıdaki gibi Az ya da çok bir şey: kilit çok iri olduğu içinHem öğe hem de koleksiyon düzeyinde kilitlemeyi etkin bir şekilde nasıl destekleyebilirim?
private readonly object lockObject = new object();
private Dictionary<int, Widget> items;
private void UpdateAllWidgets()
{
lock (this.lockObject)
{
// Update all the widgets. No widgets should be permitted to be
// updated while this is running.
}
}
private void UpdateWidget(int widgetId)
{
lock (this.lockObject)
{
// Update the widget with id = widgetId. I want to me able to
// update other widgets at the same time, however.
}
}
Şimdi performansla sorunlarla çalıştırıyorum. Tek bir öğe güncellenmişken (diğer öğelerin aynı anda güncellenmesine izin verirken) öğe düzeyinde kilitler alabilmek istiyorum ancak yine de gerektiğinde koleksiyon düzeyinde bir kilit almak için 'u kullanabilirim. Bu destek olabilecek bir kilit yapısı üzerinde
Thread 1: UpdateWidget(1);
Thread 2: UpdateWidget(2); // This can run before UpdateWidget(1)
// completes.
Thread 1: UpdateWidget(1);
Thread 2: UpdateAllWidgets(); // This has to wait for UpdateWidget(1)
Thread 3: UpdateWidget(2); // This has to wait for UpdateAllWidgets()
Thread 4: UpdateWidget(3); // This has to wait for UpdateAllWidgets(), but
// not UpdateWidget(2)
Herhangi fikirler: Yani davranış aşağıdaki gibi görünecektir? Yukarıdaki örnek, basitleştirilmiş bir sürüm için gereklidir, ancak daha önce ConcurrentDictionary yetersiz kalmıştır. Örneğin, UpdateWidget içinde gerçekleştirilen eylemler, basit yerinde güncellemelerden daha fazlasıdır. Bu öğeyi etkileyen veritabanı güncellemelerini içerebilirler.
Bu tür bir senaryona sahip olduğumda her iki yaklaşımı da kümülatırım. Bir ConcurrentDictionary, ancak her değeri bir kapsayıcıya sarmak, değişiklik yapmadan önce kilitleyebilirim. Toplama düzeyinde kilitleme işlemek için küresel bir ReaderWriterLockSlim eklemeniz gerekir –
Koleksiyon öğeleri çok iş parçacıklı bir şekilde ekledi mi (veya kaldırıldı)? Veya koleksiyonun statik boyutu var ve öğeler yeni güncellendi mi? –
@ MatiasCicero- Evet, öğeler başka konulara eklenip çıkarılabilir. Ekler, öğe düzeyinde güncellemeleri engellememelidir; Bir kaldırma işlemi yalnızca bu öğeyi engelleyecektir. –