La compréhension de std::atomique::compare_exchange_weak() en C++11

bool compare_exchange_weak (T& expected, T val, ..);

compare_exchange_weak() est l'un de comparer échange de primitives fournies en C++11. C'est faible dans le sens où elle renvoie false, même si la valeur de l'objet est égale à expected. Cela est dû à fausse panne sur certaines plates-formes où une séquence d'instructions (au lieu d'un seul comme sur x86) sont utilisés pour la mettre en œuvre. Sur de telles plates-formes, changement de contexte, le rechargement de la même adresse (ou de la ligne de cache) par un autre thread, etc peut échouer la primitive. C'est spurious que ce n'est pas la valeur de l'objet (n'est pas égal à expected) qui n'a pas l'opération. Au lieu de cela, c'est une sorte de problèmes de timing.

Mais ce qui m'intrigue, c'est ce qui est dit dans C++11 Norme (ISO/IEC 14882),

29.6.5
..
Une conséquence de la fausse panne, c'est que presque toutes les utilisations de la faiblesse des
comparez et d'échange sera dans une boucle.

Pourquoi a-t-il d'être dans une boucle dans presque toutes les utilisations ? Est-ce à dire que nous ne boucle lorsqu'il échoue à cause de fausses pannes? Si c'est le cas, pourquoi ne nous dérange pas utiliser compare_exchange_weak() et écrire la boucle de nous-mêmes? Nous pouvons simplement utiliser compare_exchange_strong() qui, je pense, devrait se débarrasser de la fausse échecs pour nous. Quels sont les cas d'utilisation courants de compare_exchange_weak()?

Une autre question. Dans son livre "C++ de la Simultanéité Dans l'Action" Anthony dit,

//Because compare_exchange_weak() can fail spuriously, it must typically
//be used in a loop:

bool expected=false;
extern atomic<bool> b; //set somewhere else
while(!b.compare_exchange_weak(expected,true) && !expected);

//In this case, you keep looping as long as expected is still false,
//indicating that the compare_exchange_weak() call failed spuriously.

Pourquoi est !expected il y a dans la condition de la boucle? Est-il là pour éviter que tous les threads peuvent mourir de faim et ne fait aucun progrès depuis un certain temps?

Edit: une dernière question)

Sur les plates-formes qu'aucun matériel CAS d'instructions en vigueur, les faibles et les forts de la version sont mises en œuvre à l'aide de LL/SC (comme ARM, PowerPC, etc). Donc, il y a une différence entre les deux boucles? Pourquoi, si? (Pour moi, ils devraient avoir des performances similaires.)

//use LL/SC (or CAS on x86) and ignore/loop on spurious failures
while (!compare_exchange_weak(..))
{ .. }

//use LL/SC (or CAS on x86) and ignore/loop on spurious failures
while (!compare_exchange_strong(..)) 
{ .. }

Je viens w/cette dernière question les gars, vous tous mentionner qu'il ya peut-être une différence de performance à l'intérieur d'une boucle. Il est également mentionné par le C++11 Norme (ISO/IEC 14882):

Quand a comparer-et-exchange est dans une boucle, la version faible rendement
de meilleures performances sur certaines plates-formes.

Mais comme analysé ci-dessus, les deux versions dans une boucle doit donner le même rendement. Quelle est la chose qui me manque?

  • W/r/t à la première question, dans de nombreux cas, vous avez besoin de boucle, de toute façon (si vous utilisez le fort ou le faible version), et la version faible, peut avoir de meilleures performances que le fort.
  • À la fois faible et forte autorités de certification sont mis en œuvre "à l'aide de LL/SC", de la même manière que les deux tri à bulles et quicksort sont mis en œuvre "à l'aide de swap"; c'est, dans le sens que c'est la primitive de fonctionnement utilisé pour obtenir la tâche accomplie. Ce qu'ils enrouler autour de LL/SC est très différent. La faiblesse de la SAE est juste LL/SC. Forte SAE LL/SC avec un tas d'autres trucs.
  • forums.manning.com/posts/list/33062.page est-il de l'aide?
  • avec la réponse dans ce lien, je ne vois pas pourquoi "la version faible, d'obtenir de meilleurs performances sur certaines plates-formes", comme indiqué dans la Norme.
  • Sur d'autres, compare_exchange_weak peut échouer faussement, en raison des interruptions ou des actions d'autres processeurs ou les threads. Sur ces plateformes, compare_exchange_strong est effectivement une boucle sur compare_exchange_weak - si elle n'a pas faussement puis il les boucles de nouveau. Est-il utile? Peut-être que je me trompe
InformationsquelleAutor Eric Z | 2014-08-08