CodeBlanks Logo Icon CodeBlanks

Concurrency

Concurrency ve memory model ile paralel yapı yazarsın.

std::thread ve std::atomic ile paralel toplam

Paralel iş için std::thread ile iki iş parçacığı başlatırız. Paylaşılan bir sayacı std::atomic<int> olarak tutarız; böylece iki iş parçacığı aynı anda güvenle yazabilir. total += i işlemi atomik olarak yapılır ve veri yarışı oluşmaz.

İş parçacıkları 1-4 ve 5-8 aralığını toplar. t1.join() ve t2.join() ile her iki iş parçacığının bitmesini bekleriz. Sonuç her zaman 36 olur; çünkü toplam sabittir, yalnızca yazma sırası değişir. Bu deterministik çıktı, atomic kullanımının güvenli olduğunu gösterir.

join ile bitmesini beklemek

Bir iş parçacığının bitmesini beklemek için join() çağrılır. t1.join() ana akışı durdurur ve t1 bitene kadar bekletir. Her iki iş parçacığı da bitince total tüm katkıları toplamış olur.

Sonuç 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 = 36'dır. Yazma sırası farklı olsa da toplam değişmez. join'i unutursak program iş parçacıkları bitmeden sonlanabilir ve std::terminate çağrılır. Bu yüzden join zorunludur.

Uygulama parallelSum metodunu ekle ve çağır

Önceki dersin çözümünü al (Engine sınıfı ve Factorial şablonu var). Engine sınıfının public: bölümüne static int parallelSum() metodunu ekle. Gövdesinde std::atomic<int> total{0}; tanımla, iki std::thread başlat (1-4 ve 5-8 aralıkları), her ikisini de join ile bekle ve total.load() döndür. main içinde Factorial çıktısından sonra std::cout << std::endl << Engine::parallelSum(); ekle.

Başlangıç kodu

main.cpp
#include <iostream>
#include <atomic>
#include <thread>

class Engine {
public:
    static const int Version = 1;
    // parallelSum metodunu buraya ekle
};

template <int N>
struct Factorial {
    static const int value = N * Factorial<N - 1>::value;
};

template <>
struct Factorial<0> {
    static const int value = 1;
};

int main() {
    std::cout << "Hazır" << std::endl;
    std::cout << Factorial<5>::value << std::endl;
    // parallelSum sonucunu yazdır
    return 0;
}

Örnek çözüm

main.cpp
#include <iostream>
#include <atomic>
#include <thread>

class Engine {
public:
    static const int Version = 1;
    static int parallelSum() {
        std::atomic<int> total{0};
        std::thread t1([&]() { for (int i = 1; i <= 4; ++i) total += i; });
        std::thread t2([&]() { for (int i = 5; i <= 8; ++i) total += i; });
        t1.join();
        t2.join();
        return total.load();
    }
};

template <int N>
struct Factorial {
    static const int value = N * Factorial<N - 1>::value;
};

template <>
struct Factorial<0> {
    static const int value = 1;
};

int main() {
    std::cout << "Hazır" << std::endl;
    std::cout << Factorial<5>::value << std::endl;
    std::cout << Engine::parallelSum();
    return 0;
}

Beklenen çıktı

Hazır
120
36

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 İki iş parçacığı paylaşılan bir sayacı güncellerken std::atomic ne sağlar?

main.cpp
std::atomic<int> total{0};
  • Veri yarışını önler Doğru cevap
  • Bellek kullanımını azaltır
  • İş parçacığı sayısını sınırlar
  • Derleme süresini kısaltır

Açıklama: std::atomic her yazmayı atomik yapar; veri yarışı oluşmaz.

2 Atomic sayaç başlangıç değerini tamamla

Soru
std::atomic<int> total{____};
Cevap
std::atomic<int> total{0};

Açıklama: Sayaç sıfırdan başlar ve katkılar eklenir.

3 Parçayı rolüne eşle

Kavram Anlamı
std::thread İş parçacığı başlatır
std::atomic<int> Paylaşılan güvenli sayaç
t1.join() Bitmesini bekler
total += i Atomik toplama

Uzman bölümündeki tüm dersler