C++ 11 a introduit la bibliothèque de modèles std::atomic<>
. La norme spécifie les opérations store()
et load()
pour définir/obtenir atomiquement une variable partagée par plusieurs threads.
Ma question est: les opérations d'attribution et d'accès sont-elles également atomiques?
À savoir, est:
std::atomic<bool> stop(false);
...
void thread_1_run_until_stopped()
{
if(!stop.load())
/* do stuff */
}
void thread_2_set_stop()
{
stop.store(true);
}
Équivalent à:
void thread_1_run_until_stopped()
{
if(!stop)
/* do stuff */
}
void thread_2_set_stop()
{
stop = true;
}
Les opérations d'attribution et d'accès pour les types non référencés sont-elles également atomiques?
Oui, ils sont. atomic<T>::operator T
et atomic<T>::operator=
sont équivalents à atomic<T>::load
et atomic<T>::store
respectivement. Tous les opérateurs sont implémentés dans la classe atomique de telle sorte qu'ils utiliseront les opérations atomiques comme vous vous en doutez.
Je ne sais pas ce que vous voulez dire sur les types "non référencés"? Je ne sais pas comment les types de référence sont pertinents ici.
Vous pouvez faire les deux, mais l'avantage de load()
/store()
est qu'ils permettent de spécifier l'ordre de la mémoire. Il est parfois important pour les performances, où vous pouvez spécifier std::memory_order_relaxed
tandis que atomic<T>::operator T
et atomic<T>::operator=
utiliserait le plus sûr et le plus lent std::memory_order_seq_cst
. Parfois, il est important pour l'exactitude et la lisibilité de votre code: bien que la valeur par défaut std::memory_order_seq_cst
est le plus sûr et donc le plus susceptible d'être correct, il n'est pas immédiatement clair pour le lecteur quel type d'opération (acquérir/libérer/consommer) vous faites, ou si vous effectuez une telle opération du tout (pour répondre: n'est pas ' t ordre détendu suffisant ici?).