Il y a de nombreuses questions ici. En les considérant un à la fois:
l'attribution de référence est atomique alors pourquoi Interlocked.Exchange (ref Object, Object) est-il nécessaire?
L'attribution de référence est atomique. Interlocked.Exchange ne fait pas que référence à l'affectation. Il lit la valeur actuelle d'une variable, cache l'ancienne valeur et assigne la nouvelle valeur à la variable, le tout comme une opération atomique.
mon collègue a dit que sur certaines plates-formes, il n'est pas garanti que l'attribution des références soit atomique. Mon collègue avait-il raison?
L'affectation de référence est garantie comme atomique sur toutes les plates-formes .NET.
Mon collègue raisonne à partir de fausses prémisses. Cela signifie-t-il que leurs conclusions sont incorrectes?
Pas nécessairement. Votre collègue pourrait vous donner de bons conseils pour de mauvaises raisons. Il y a peut-être une autre raison pour laquelle vous devriez utiliser Interlocked.Exchange. La programmation sans verrouillage est incroyablement difficile et au moment où vous vous écartez des pratiques bien établies adoptées par des experts dans le domaine, vous êtes dans les mauvaises herbes et vous risquez les pires conditions de course. Je ne suis ni un expert dans ce domaine ni un expert de votre code, je ne peux donc pas porter de jugement dans un sens ou dans l'autre.
produit un avertissement "une référence à un champ volatil ne sera pas considérée comme volatile" Que dois-je en penser?
Vous devez comprendre pourquoi c'est un problème en général. Cela permettra de comprendre pourquoi l'avertissement est sans importance dans ce cas particulier.
La raison pour laquelle le compilateur donne cet avertissement est que le fait de marquer un champ comme volatile signifie "ce champ va être mis à jour sur plusieurs threads - ne générez aucun code qui met en cache les valeurs de ce champ, et assurez-vous que toute lecture ou écriture de ce champ n'est pas "déplacé vers l'avant et vers l'arrière dans le temps" via les incohérences du cache du processeur. "
(Je suppose que vous comprenez déjà tout cela. Si vous n'avez pas une compréhension détaillée de la signification de volatile et de son impact sur la sémantique du cache du processeur, vous ne comprenez pas comment cela fonctionne et ne devriez pas utiliser volatile. Programmes sans verrouillage sont très difficiles à réaliser; assurez-vous que votre programme est correct parce que vous comprenez comment il fonctionne, et non par accident.)
Supposons maintenant que vous créez une variable qui est un alias d'un champ volatil en passant une référence à ce champ. Dans la méthode appelée, le compilateur n'a aucune raison de savoir que la référence doit avoir une sémantique volatile! Le compilateur générera joyeusement du code pour la méthode qui ne parvient pas à implémenter les règles pour les champs volatils, mais la variable est un champ volatil. Cela peut complètement détruire votre logique sans verrouillage; l'hypothèse est toujours qu'un champ volatil est toujours accessible avec une sémantique volatile. Cela n'a aucun sens de le traiter comme volatil parfois et pas à d'autres moments; tu dois toujours être cohérent sinon vous ne pouvez pas garantir la cohérence sur les autres accès.
Par conséquent, le compilateur vous avertit lorsque vous faites cela, car il va probablement complètement gâcher votre logique sans verrouillage soigneusement développée.
Bien sûr, Interlocked.Exchange est écrit pour s'attendre à un champ volatil et faire ce qu'il faut. L'avertissement est donc trompeur. Je le regrette beaucoup; ce que nous aurions dû faire est d'implémenter un mécanisme par lequel un auteur d'une méthode comme Interlocked.Exchange pourrait mettre un attribut sur la méthode en disant "cette méthode qui prend une référence applique une sémantique volatile sur la variable, donc supprimez l'avertissement". Peut-être que dans une prochaine version du compilateur nous le ferons.
var myresult = await Task.Factory.CreateNew(() => MyWork(exclusivelyLocalStuffOrValueTypeOrCopy));
.Soit votre collègue se trompe, soit il sait quelque chose que la spécification du langage C # ne sait pas.
5.5 Atomicité des références variables :
Ainsi, vous pouvez écrire dans la référence volatile sans risquer d'obtenir une valeur corrompue.
Vous devez bien sûr faire attention à la manière dont vous décidez quel thread doit récupérer les nouvelles données, afin de minimiser le risque que plus d'un thread à la fois le fasse.
la source
Interlocked.Exchange <T>
Il change et renvoie la valeur d'origine, c'est inutile car vous ne voulez que le changer et, comme l'a dit Guffa, c'est déjà atomique.
À moins qu'un profileur ne prouve qu'il s'agit d'un goulot d'étranglement dans votre application, vous devriez envisager de déverrouiller les verrous, c'est plus facile à comprendre et à prouver que votre code est correct.
la source
Iterlocked.Exchange()
n'est pas seulement atomique, il s'occupe également de la visibilité de la mémoire:Problèmes de synchronisation et de multiprocesseur
Cela signifie qu'en plus de l'atomicité, il garantit que:
la source