Sobes.tech
Middle

Çok iş parçacıklı çalışma sırasında hangi sorunlar ortaya çıkabilir ve bunlar nasıl önlenebilir?

sobes.tech yapay zeka

AI'dan gelen yanıt

Çok iş parçacıklı çalışmada sorunlar ve bunlardan nasıl kaçınılır:

  • Veri Yarışı (Data Race): Birden fazla iş parçacığının aynı anda ortak verilere erişmesi ve en az birinin bu verileri değiştirmesi durumudur. Bu, öngörülemeyen davranışlara ve hatalı sonuçlara yol açabilir.

    • Çözüm: lock (Monitor), Mutex, Semaphore, ReaderWriterLockSlim, SpinLock gibi senkronizasyon mekanizmalarının kullanılması.
    // lock kullanımı örneği
    private object _lockObject = new object();
    private int _counter = 0;
    
    public void Increment()
    {
        lock (_lockObject)
        {
            _counter++; // Kritik bölüm
        }
    }
    
  • Ölümlü Kilit (Deadlock): İki veya daha fazla iş parçacığının, birbirlerinin tuttuğu kaynakları bekleyerek kilitlenmesi durumudur.

    • Çözüm:
      • Kilitlerin iç içe kullanılmasından kaçınmak.
      • Kilitleri önceden belirlenmiş bir sırayla almak.
      • Monitor.TryEnter veya Mutex.WaitOne(timeout) kullanmak, zaman aşımı ile alma denemeleri yapmak.
  • Açlık (Starvation): Bir veya daha fazla iş parçacığının, diğerlerinin sürekli meşgul ettiği kaynaklara uzun süre erişememesi durumu.

    • Çözüm:
      • Adil (fair) senkronizasyon mekanizmalarının kullanılması (tüm mekanizmalar adil olmayabilir).
      • Tasarımı gözden geçirmek, büyük kritik bölümleri bölmek.
      • Önceliklerin doğru yönetildiği iş parçacığı havuzları kullanmak (önceliklerin değiştirilmesi başka sorunlara yol açabilir).
  • Yanlış Yayınlama (Improper Publication): Bir nesnenin, yapıcı tamamlanmadan veya tüm alanları doğru şekilde başlatılmadan diğer iş parçacıklarına erişilebilir hale gelmesi durumu.

    • Çözüm:
      • Değişmez (immutable) nesnelerin kullanılması.
      • Lazy<T> gibi iş parçacığı güvenli tembel başlatma mekanizmalarının kullanılması.
      • Nesnenin ilk yayınında senkronizasyon yapılması.
  • Görünürlük Sorunları (Visibility Issues): Bir iş parçacığında yapılan değişikliklerin, diğerleri tarafından hemen görülmemesi, işlemci önbelleklemesi veya derleyici optimizasyonları nedeniyle olabilir.

    • Çözüm:
      • Çok iş parçacıklı erişimlerde volatile anahtar kelimesinin kullanılması (okumanın her zaman bellekte yapılmasını ve yazmanın belleğe aktarılmasını sağlar).
      • lock, Monitor gibi senkronizasyon mekanizmalarının kullanılması, bunlar bellek bariyerleri içerir.
    // volatile kullanımı örneği
    private volatile bool _stopRequested = false;
    
    public void WorkerMethod()
    {
        while (!_stopRequested)
        {
            // İş yapma
        }
    }
    
    public void RequestStop()
    {
        _stopRequested = true;
    }
    

Sorunların ve çözümlerin özet tablosu:

Sorun Açıklama Çözüm
Veri Yarışı Paylaşılan ve değiştirilebilir verilere eşzamanlı erişim. lock, Mutex, Semaphore, ReaderWriterLockSlim, SpinLock.
Ölümlü Kilit (Deadlock) İş parçacıkları, birbirlerinin tuttuğu kaynakları beklerken kilitlenir. İç içe kilitleri önlemek, sıralı edinim, zaman aşımı kullanmak.
Açlık (Starvation) Bir veya daha fazla iş parçacığı, uzun süre kaynaklara erişemez. Adil mekanizmalar, tasarımı gözden geçirme, öncelik yönetimi dikkatli yapılmalı.
Yanlış Yayınlama Nesne, tam olarak başlatılmadan diğer iş parçacıklarına erişilebilir. Değişmez nesneler, Lazy<T>, yayınlama sırasında senkronizasyon.
Görünürlük Sorunları Bir iş parçacığında yapılan değişiklikler diğerleri tarafından hemen görülmez. volatile, bellek bariyerleri (senkronizasyon mekanizmalarıyla).

Ayrıca, yüksek seviyeli soyutlamalar olan Task Parallel Library (TPL) ve async/await kullanmak önerilir. Bu, paralellik ve asenkron yönetimini kolaylaştırır ve doğru kullanıldığında bu sorunların oluşma olasılığını azaltır.