J'essaie un support C ++ 0x et il y a un problème que je suppose ne devrait pas être là. Soit je ne comprends pas le sujet ou GCC a un bug.
J'ai le code suivant, initialement Ce code échoue parfois, mais pourquoi? Le problème ici est probablement une réorganisation de la mémoire, mais toutes les opérations atomiques sont cohérentes de manière séquentielle par défaut et je ne suis pas explicitement relaxé de ces opérations. Je compose ce code sur x86, ce qui autant que je sache ne devrait pas avoir de problèmes de commande. Pouvez-vous s'il vous plaît expliquer ce que le problème est? P> Le résultat peut être visualisé Ici . p> p> x code> et
y code> est égal. Filf 1 incrémente toujours
x code> d'abord puis incréments
y code>. Les deux sont des valeurs entières atomiques, il n'y a donc aucun problème avec l'incrément du tout. Le fil 2 vérifie si le
x code> est inférieur à
y code> et affiche un message d'erreur si oui. P>
4 Réponses :
Le problème pourrait être dans votre test: Le thread pourrait évaluer x code> et ne pas contourner pour évaluer
y code> jusqu'à ce que plus tard. p> p>
Je suppose que c'est le problème, la question est pourquoi? En réalité, les opérations atomiques cohérentes séquentiellement doivent l'empêcher, ne doivent-ils pas?
Merci beaucoup! Le problème est une séquence non spécifiée d'évaluation d'expression, si simple :)
@confucius: Bien que votre scénario puisse avoir une dépendance à la commande selon laquelle les variables pourraient être lues, la question plus générale est que la lecture de 2 instances atomiques différentes n'est pas atomique.
Bien sûr, je pense que dans la situation actuelle, une ligne trompeuse dans le code était (x
Il y a un problème avec la comparaison:
int yval = y; int xval = x; if (xval < yval) { /* ... */ }
Merci! C'est ça. Désolé les gars, ne peuvent pas plus, https est bloqué dans le bureau et je ne peux pas me connecter :(
Premièrement, je suis d'accord avec "Michael Burr" et "James McNellis". Votre test n'est pas juste et il y a une possibilité légitime d'échouer. Cependant, même si vous réécrivez le test comme "James McNellis" suggère que le test peut échouer. P>
première raison pour cela est que vous n'utilisez pas la sémantique code> volatile code>, d'où le compilateur peut effectuer des optimisations à votre code (qui sont censés être corrects dans un boîtier à un seul fileté). p>
mais même avec Je pense que vous ne comprenez pas complètement le concept de la réorganisation de la mémoire em>. En réalité, la réorganisation de la mémoire / écriture peut se produire à deux niveaux: p>
Utilisation de Pour empêcher cela, vous devez mettre des instructions spéciales forts> clôture de mémoire forte> dans le code (désigné pour la CPU, contrairement à en x86 / x64 Il y a de nombreuses instructions de clôture de mémoire différentes. Aussi toutes les instructions avec Plus d'informations ici: P>
volatile code> Votre code n'est pas garanti de fonctionner. P>
volatile code> empêche le (1). Cependant, vous n'avez rien fait pour empêcher (2) - l'accès à la mémoire de la réorganisation du matériel
volatile code> qui est uniquement pour le compilateur uniquement). P>
Serrure code> Sémantique par défaut des problèmes de mémoire complète de la mémoire. P>
Valdo - Pas besoin d'utiliser des volatiles ici, car les barrières de mémoire par défaut générées par des opérations atomiques C ++ 0x empêchent les deux (1) et (2).
de temps en temps, x code> sera envelopper sur 0 juste avant
y code> wraps autour de zéro. À ce stade,
y code> sera légitimement supérieur à
x code>. P>
A pris un coup de feu à la modifier. Il peut également être noté que le débordement signé conduit à un comportement indéfini, bien que le débordement non signé s'envole comme prévu.
Se mettre d'accord. Le trop-plein n'était pas censé arriver, cela a été fait juste pour le test, mais cela pourrait être un problème aussi. Merci.
En réalité, il s'agit d'une mise en œuvre expérimentale de C ++ 0x, la seconde est donc possible, mais je crois que le premier est plus probable: p
Le code posté ci-dessus produira toujours
"erreur" code>, (
x code> sera toujours supérieur ou égal à
y code>) est-ce que tu voulais?
Pourquoi si (x
Quelle est la commande de mémoire par défaut pour l'incrément? Un magasin garantit-il une libération? [Mon expérience avec le modèle de mémoire C ++ 0x est limitée]
@Paul: J'ai immédiatement accepté avec vous, mais vous pensions et je pensais "si c'est pas i> ce qu'il teste, impression
" erreur " code>. Mais le code est si ce > est i>, impression it.thread 2 peut voir des paires du formulaire
(n, n) code> et
(n + 1, n) code>. Dans les deux cas,
x est faux. Il y a une séquence qui le déclenche, cependant. @james: Ouais.
"Quelle est la commande de mémoire par défaut pour l'incrément?" - Séquentiellement cohérent est par défaut.
@confucius: j'ai pensé; Un ordre détendu par défaut serait terrible.
@Gman: Vous avez raison bien sûr. Je pense que j'ai passé beaucoup trop longtemps à regarder le code pendant une journée.