Ho provato a cercare dettagli su questo, ho persino letto lo standard su mutex e atomics ... ma non riuscivo a capire le garanzie di visibilità del modello di memoria C++ 11. Da quello che ho capito la caratteristica molto importante del Mutex, l'esclusione reciproca sta assicurando visibilità. Aka non è sufficiente che solo un thread per volta stia aumentando il contatore, è importante che il thread aumenti il contatore che è stato memorizzato dal thread che era l'ultimo usando il mutex (non so davvero perché le persone non lo menzionino di più quando discutono mutex, forse ho avuto cattivi insegnanti :)). Quindi, da quello che posso dire doesnt atomica rispettare visibilità immediata: (da parte della persona che mantiene boost :: filo e ha implementato C++ 11 filo e biblioteca mutex):Ordinamento e visibilità del modello di memoria?
una recinzione con memory_order_seq_cst non impone immediata visibilità ad altri thread (e nemmeno un'istruzione MFENCE). I vincoli di ordinamento della memoria C++ 0x sono proprio quello --- che ordina i vincoli . Le operazioni memory_order_seq_cst formano un ordine totale, ma non ci sono restrizioni su cosa sia quell'ordine, eccetto che deve essere concordato su tutti i thread, e non deve violare altri vincoli di ordinazione. In particolare, i thread potrebbero continuare a visualizzare valori "stantio" per un po 'di tempo, a condizione che visualizzino i valori in un ordine coerente con i vincoli .
E io sono OK con quello. Ma il problema è che ho difficoltà a capire quali sono i costrutti C++ 11 per quanto riguarda l'atomico sono "globali" e che assicurano solo la coerenza delle variabili atomiche. In particolare ho la comprensione che (se esiste) dei seguenti memory ordinamenti garantiscono che ci sarà una recinzione di memoria prima e dopo il carico e lo memorizza: http://www.stdthread.co.uk/doc/headers/atomic/memory_order.html
Da quello che posso dire std :: memory_order_seq_cst inserisce barriera mem mentre altri applicano solo l'ordine delle operazioni su determinate posizioni di memoria.
Così qualcuno può chiarire la situazione, presumo un sacco di persone stanno andando essere fare errori orribili utilizzando std :: atomica, specialmente se essi non utilizzare di default (std :: memory_order_seq_cst memoria ordinazione)
2. se io' m destra vuol dire che la seconda linea è redundand in questo codice:
atomicVar.store(42);
std::atomic_thread_fence(std::memory_order_seq_cst);
3. fare std :: atomic_thread_fences hanno stessi requisiti mutex in un senso che per assicurare la coerenza seq su nonatomic vars bisogna fare std :: atomic_thread_fence (std :: memory_order_seq_cst); prima del caricamento e std :: atomic_thread_fence (std :: memory_order_seq_cst);
dopo i negozi?
4.
{
regularSum+=atomicVar.load();
regularVar1++;
regularVar2++;
}
//...
{
regularVar1++;
regularVar2++;
atomicVar.store(74656);
}
equivalente a
std::mutex mtx;
{
std::unique_lock<std::mutex> ul(mtx);
sum+=nowRegularVar;
regularVar++;
regularVar2++;
}
//..
{
std::unique_lock<std::mutex> ul(mtx);
regularVar1++;
regularVar2++;
nowRegularVar=(74656);
}
Credo di no, ma vorrei essere sicuro.
MODIFICA: 5. Può affermare il fuoco?
Esistono solo due thread.
atomic<int*> p=nullptr;
primo thread scrive
{
nonatomic_p=(int*) malloc(16*1024*sizeof(int));
for(int i=0;i<16*1024;++i)
nonatomic_p[i]=42;
p=nonatomic;
}
secondo thread legge
{
while (p==nullptr)
{
}
assert(p[1234]==42);//1234-random idx in array
}
quindi in 5) per (int i = 0; i <16 * 1024; ++ i) nonatomic_p [i] = 42; non può essere spostato dopo l'assegnazione di p? Perché memory_order_seq presumo abbia ragione, voglio solo controllare. Buona risposta a BTW! – NoSenseEtAl
BTW potresti approfondire perché 4) è la corsa dei dati? – NoSenseEtAl
Sì, hai ragione in 5 --- i compiti su 'nonatomic_p [i]' non possono essere spostati dopo l'assegnazione di 'p'. –