C++11 introduceerde de std::atomic<>
sjabloonbibliotheek. De standaard specificeert de bewerkingen store()
en load()
om atomair een variabele in te stellen/op te halen die door meer dan één thread wordt gedeeld.
Mijn vraag is zijn toewijzings- en toegangsbewerkingen ook atomair?
Met name is:
std::atomic<bool> stop(false);
...
void thread_1_run_until_stopped()
{
if(!stop.load())
/* do stuff */
}
void thread_2_set_stop()
{
stop.store(true);
}
Equivalent aan:
void thread_1_run_until_stopped()
{
if(!stop)
/* do stuff */
}
void thread_2_set_stop()
{
stop = true;
}
Antwoord 1, autoriteit 100%
Zijn toewijzings- en toegangsbewerkingen voor niet-referentietypen ook atomair?
Ja, dat zijn ze. atomic<T>::operator T
en atomic<T>::operator=
zijn equivalent aan atomic<T>::load
en atomic<T>::store
respectievelijk. Alle operatoren zijn geïmplementeerd in de atomaire klasse, zodat ze atomaire bewerkingen zullen gebruiken zoals je zou verwachten.
Ik weet niet zeker wat je bedoelt met ‘niet-referentie’-typen? Ik weet niet zeker hoe referentietypes hier relevant zijn.
Antwoord 2, autoriteit 55%
Je kunt beide doen, maar het voordeel van load()
/store()
is dat je de geheugenvolgorde kunt specificeren. Het is soms belangrijk voor prestaties, waarbij u std::memory_order_relaxed
kunt specificeren terwijl atomic<T>::operator T
en atomic<T>::operator=
zou de meest veilige en langzame std::memory_order_seq_cst
gebruiken. Soms is het belangrijk voor de juistheid en leesbaarheid van uw code: hoewel de standaard std::memory_order_seq_cst
het meest veilig is en dus hoogstwaarschijnlijk correct is, is het voor de lezer niet meteen duidelijk wat voor /release/consume) die u aan het doen bent, of dat u een dergelijke operatie überhaupt uitvoert (om te antwoorden: is een ontspannen volgorde hier niet voldoende?).