2015-04-16 23 views
8

Qual è la definizione minimo richiesto perx s' tipo per questo codice lavorare, considerando la sincronizzazione implicita durante la creazione/unisce un filo: std::atomic? volatile? Niente?sincronizzazione implicita durante la creazione/filetti di giunzione

#include <thread> 
#include <cassert> 
int main() { 
    int x = 123; // *** 
    std::thread([ & ] { assert(x == 123); x = 321; }).join(); 
    assert(x == 321); 
    return 0; 
} 
+0

Ti consigliamo di leggere [questa risposta] (http://stackoverflow.com/a/3114174/1769720) a una domanda correlata. – didierc

+2

'std :: thread ([&] {assert (x == 123); x = 321;}) .join();' Non c'è accesso simultaneo a 'x', potresti chiamare il lambda in sequenza per ottenere lo stesso comportamento. 'volatile' non serve mai per la sicurezza del filo, BTW. –

risposta

11

L'invocazione del costruttore std::thread s' è sincronizzato e avviene prima l'invocazione della copia della funzione filo (30.3.1.2/6).

thread::join fornisce una garanzia di sincronizzazione simile: il completamento del thread avviene prima dei ritorni join (30.3.1.4/7).

Il codice crea una discussione e la unisce immediatamente. Sebbene il tuo lambda acquisisca per riferimento, non esiste concorrenza (il codice viene eseguito come se sequenziale) e le garanzie fornite da std::thread assicurano che non sia necessario alcun framing speciale per proteggere x. L'affermazione non fallirà mai.

Supponendo che lo snippet di codice fosse diverso in modo da avere un accesso simultaneo di qualche tipo, è necessario utilizzare std::atomic o un mutex. volatile non sarebbero più sufficienti (eccetto per coincidenza).

+0

Capisco che con la specifica 'volatile' non è sufficiente perché solo i tipi' std :: atomic' sono dichiarati privi di dati-race, ma di cosa si tratta 'int', sotto la cappa, che potrebbe rendere è filante? Come riconosco un errore? È perché i quattro byte dell'int possono essere scritti in due blocchi di 2 byte su alcune piattaforme, mentre su altre piattaforme che hanno inte-32 bit nativi funzionerà sempre, anche se è ancora sbagliato? Su alcune piattaforme, potrebbe 'std :: atomic ' essere solo un alias per 'int'? Studente davvero curioso qui. – antiduh

+1

@antiduh Non si tratta solo di leggere o scrivere quella variabile da sola. L'uso dell'atomica limita anche il riordino. –

+0

@antiduh: Il tipo atomico e le sue specializzazioni garantiscono di avere certe (qualunque si scelga) le garanzie di ordinazione. Ad esempio, è garantito che una scrittura dipendente (o una scrittura indipendente) sia globalmente visibile prima di un'operazione atomica. Nessuna garanzia è data da "volatile". Potrebbe "funzionare", ma questa è una coincidenza. Per quanto riguarda la scrittura di numeri interi, supponendo le CPU tradizionali e il corretto allineamento, hai ragione. non sono possibili le scritture "int" non atomiche. Tuttavia, questo non è formalmente garantito e non è portabile, nessun ordine definito e le operazioni RMW (ad esempio '++ x') non sono atomiche. – Damon