2013-07-07 14 views
6

Bu iplik güvenli midir?Başka bir iş parçacığı tarafından yazıldıktan sonra ve bu iş parçacığı birleştirildikten sonra ana iş parçacığından bir değişkene erişmek güvenli midir?

int x = 0; 
std::thread([&]{ x = 1; }).join(); 
std::cout << x; 

Değişken x'e atomik veya kilit kullanmadan iki iş parçacığından erişilebilir. Ancak, join() numaralı çağrı, erişimi ardışık olacak şekilde x'e zorlar.

Burada bir bellek bariyeri mi gerekiyor?

+3

veri yok = bunun için gerek yok – user2485710

cevap

11

Evet, o belirli kod parçacığı iplik güvenlidir; engeller veya kilitler gerekli değildir.

Bu

Kodunuzdaki göre olayların zaman çizelgesi geçerli: Gördüğünüz gibi

thread 1 
-------- 
    | 
    int x = 0; 
    (write 0 to x) 
    | 
    std::thread    thread 2 
    (start thread 2) --------> -------- 
    |       | 
    join();      x = 1; 
    (thread 1 suspended)   (write 1 to x) 
    .       | 
    .       thread 2 returns 
    .       | 
    (thread 1 resumes) <------- x 
    | 
    std::cout << x; 
    (read from x) 
    | 
    thread 1 returns 
    | 
    x 

, hiçbir noktada olduğu x birden fazla iş parçacığı tarafından erişilen. Aslında, join()'un kullanımı, tüm erişimlerix'un sıralı olarak düzenlendiğinden emin olduğunuz şekilde gerçekleştirir. join(), kilitlerden aldığınız senkronizasyonun yerine senkronizasyonu sağlar.

Temel olarak, sahip olduğunuz sıfır eşzamanlılık ile çoklu iş parçacığına sahip olmanın bir örneğidir.

Elbette, bu yalnızca sağladığınız kod snippet'inde iş parçacığı oluşturduktan hemen sonra gerçekleşen join() numaralı çağrı nedeniyle doğrudur. Bir yarış tanıtacak bu şekilde join() sırasını değiştirme

thread 1 
-------- 
    | 
    int x = 0; 
    (write 0 to x) 
    | 
    std::thread    thread 2 
    (start thread 2) --------> -------- 
    |       | 
    std::cout << x;    x = 1; 
    (read from x)    (write 1 to x) <-- PROBLEM! 
    |       | 
    join();      | 
    (thread 1 suspended)   | 
    .       | 
    .       thread 2 returns 
    .       | 
    (thread 1 resumes) <------- x 
    | 
    thread 1 returns 
    | 
    x 

:

int x = 0; 
std::thread t([&]{ x = 1; }); 
std::cout << x; 
t.join(); // Move join() call here 

zaman çizelgesi yerine aşağıdaki gibi görünebilir: Bunun yerine böyle bir şey olsaydı.

+2

Bu 'Evet' demenin çok kapsamlı bir yoludur. –

+1

Şu andan itibaren iş parçacıkları hakkında yayınlamak için bu diyagram stilini kullanacağımı düşünüyorum. – Prime

+0

join() özel bir garantiye sahip olmadıkça, ana iş parçacığı, join() öğesinden sonra bile x'in önbelleğe alınmış değerini kullanabilir ve eski sonucu yazdırabilir, hayır? – mitchnull

İlgili konular