C#'ta çoklu iş parçacıkları ortak bir duruma eriştiğinde, iş parçacıkları ve görevlerle çalışma nasıl gerçekleşir?
sobes.tech yapay zeka
AI'dan gelen yanıt
C# dilinde çoklu akışlar tarafından paylaşılan bir durumla çalışırken senkronizasyon sorunları ve yarış durumları ortaya çıkabilir. İş akışlarının güvenliğini sağlamak için aşağıdaki mekanizmalar kullanılır:
-
Kilitleme (Locking):
lockoperatörü, yalnızca bir akışın korunan kaynağa erişebileceği kritik bir bölüm oluşturmak için kullanılır.- Genellikle
private readonly objectolan bir nesne kilidi kullanılır ve senkronizasyon için kullanılır.
// lock kullanım örneği private readonly object _lockObject = new object(); private int _sharedCounter = 0; public void IncrementCounter() { lock (_lockObject) { _sharedCounter++; // Kritik bölüm } } -
Atomik işlemler:
System.Threading.Interlockedsınıfı,Increment,Decrement,Add,Exchangegibi atomik işlemler sağlar ve bu işlemler akış güvenlidir, açık kilitlemeye gerek kalmadan yapılabilir.
// Interlocked kullanım örneği private volatile int _sharedValue = 0; // volatile, değişikliklerin görünürlüğü için public void UpdateValue(int newValue) { Interlocked.Exchange(ref _sharedValue, newValue); // Atomik atama } public void IncrementValue() { Interlocked.Increment(ref _sharedValue); // Atomik artırma }volatile, değişikliklerin akışlar arasında görünürlüğünü sağlar, ancak çok aşamalı işlemlerin atomikliğini garanti etmez. Atomik işlemler içinInterlockedkullanılmalıdır.
-
System.ThreadingveSystem.Threading.Tasksiçindeki senkronizasyon sınıfları:Monitor:lock'a kıyasla daha düşük seviyeli bir kilitleme mekanizması.Mutex: bir kaynağa erişimi birden fazla işlem arasında senkronize eder.SemaphoreSlim: aynı anda kaynağa erişebilecek akışların sayısını sınırlar.ReaderWriterLockSlim: birden fazla akışın aynı anda okumasına izin verir, ancak yalnızca bir akış yazabilir.
-
İş parçacığı güvenli koleksiyonlar:
System.Collections.Concurrentisim alanı, özellikle çoklu iş parçacığı erişimi için tasarlanmış koleksiyonlar (ConcurrentBag<T>,ConcurrentDictionary<TKey, TValue>,ConcurrentQueue<T>,ConcurrentStack<T>) içerir. Bu koleksiyonların kullanımı, temel koleksiyon işlemlerinde manuel senkronizasyon ihtiyacını ortadan kaldırır.
// ConcurrentDictionary kullanım örneği private ConcurrentDictionary<string, int> _sharedData = new ConcurrentDictionary<string, int>(); public void AddOrUpdateData(string key, int value) { _sharedData.AddOrUpdate(key, value, (k, oldValue) => oldValue + value); } -
Değiştirilemez nesneler:
- Değiştirilemez (immutable) nesnelerin oluşturulması, oluşturulduktan sonra durumlarının değiştirilemeyeceği anlamına gelir. Paylaşılan durumu temsil eden değiştirilemez bir nesne varsa, birden fazla akış onu güvenle okuyabilir ve senkronize olmadan kullanabilir. Durum güncellemesi, yeni bir nesne örneği oluşturmaya indirgenir.
TPL (Task Parallel Library) içindeki görevlerle (Task) çalışırken, paylaşılan duruma erişimde senkronizasyonu da göz önünde bulundurmak gerekir. TPL, paralel işlemlerin oluşturulmasını ve yönetimini kolaylaştırır, ancak paylaşılan verilerle çalışırken akış güvenliğini sağlama sorumluluğunu ortadan kaldırmaz.
Uygun senkronizasyon mekanizmasının seçimi, belirli göreve ve paylaşılan duruma erişim özelliklerine bağlıdır.