Sobes.tech
Middle

İş parçaları arasındaki etkileşim nasıl senkronize edilir?

sobes.tech yapay zeka

AI'dan gelen yanıt

C++'ta birkaç temel iş parçacığı senkronizasyon mekanizması vardır:

  • Mutexler: Karşılıklı dışlama sağlar. Aynı anda yalnızca bir iş parçacığı bir mutex'e sahip olabilir. Paylaşılan kaynakların eşzamanlı erişimini önlemek için kullanılır.

    #include <mutex>
    
    std::mutex myMutex;
    
    void criticalSection() {
        std::lock_guard<std::mutex> lock(myMutex); // Mutex'i edin
        // Paylaşılan kaynakla çalışma
    } // Mutex, kapsam dışına çıkıldığında otomatik olarak serbest bırakılır
    
  • Semaforlar: Sınırlı sayıda kaynağa erişimi kontrol eder. Bir semafor, kullanılabilir kaynakların sayısını gösteren bir sayaç içerir. İş parçacıkları sayacı azaltabilir (kaynak almak için) veya artırabilir (serbest bırakmak için).

    #include <semaphore.h> // Genellikle POSIX sistemlerde kullanılır
    
    sem_t mySemaphore;
    
    void initSemaphore(int count) {
        sem_init(&mySemaphore, 0, count); // Sayaç ile semaforun başlatılması
    }
    
    void acquireResource() {
        sem_wait(&mySemaphore); // Sayacı azaltır, 0 ise bloklar
        // Kaynak kullanımı
    }
    
    void releaseResource() {
        sem_post(&mySemaphore); // Sayacı artırır
    }
    
  • Koşul Değişkenleri: İş parçacıklarının belirli bir koşulu beklemesine olanak tanır. Genellikle mutexlerle birlikte kullanılır. Bekleyen iş parçacığı mutex'i serbest bırakır ve başka bir iş parçacığı koşulun yerine getirildiğini bildirdiğinde tekrar devreye girer.

    #include <condition_variable>
    #include <mutex>
    #include <queue>
    
    std::condition_variable myCondition;
    std::mutex myMutex;
    std::queue<int> myQueue;
    
    void producer(int value) {
        std::lock_guard<std::mutex> lock(myMutex);
        myQueue.push(value);
        myCondition.notify_one(); // Bir bekleyen iş parçacığını bilgilendir
    }
    
    int consumer() {
        std::unique_lock<std::mutex> lock(myMutex);
        myCondition.wait(lock, [&]{ return !myQueue.empty(); }); // Koşulu bekle
        int value = myQueue.front();
        myQueue.pop();
        return value;
    }
    
  • Atomik Değişkenler: Basit işlemleri (okuma, yazma, değiştirme) atomik olarak gerçekleştirmeye olanak tanır, bu işlemler için mutex kullanmaya gerek kalmadan.

    #include <atomic>
    
    std::atomic_int atomicCounter(0);
    
    void incrementCounter() {
        atomicCounter++; // Atomik artış
    }
    
  • Barikatlar: Birden fazla iş parçacığını senkronize eder, böylece hiçbiri barikere ulaşmadan devam edemez.

    #include <barrier> // C++20
    
    std::barrier myBarrier(3); // 3 iş parçacığı için bariyer
    
    void workerThread() {
        // İşin bir bölümünü yap
        myBarrier.arrive_and_wait(); // Tüm iş parçacıklarının bariyere ulaşmasını bekle
        // Sonraki iş bölümünü yap
    }
    

Belirli bir mekanizmanın seçimi, iş parçacıkları arasındaki etkileşimin doğasına bağlıdır:

  • Mutexler: En yaygın kullanılan ortak verilerin korunma yöntemidir.
  • Semaforlar: Sınırlı kaynaklara erişimi yönetir.
  • Koşul Değişkenleri: Bir olayın veya durumun gerçekleşmesini bekler.
  • Atomik Değişkenler: Basit ve atomik işlemleri verimli şekilde gerçekleştirir.
  • Barikatlar: İş parçacıklarının bir sonraki aşamaya birlikte geçmesini sağlar.