référence affectation est atomique alors pourquoi est Interloqué.De change(réf Object, Object) nécessaires?
Dans mon multithread service web asmx j'avais un champ de classe _allData de mon propre type SystemData qui se compose de quelques List<T>
et Dictionary<T>
marqué comme volatile
. Le système de données (_allData
) est actualisée une fois dans un certain temps et je le fais par la création d'un autre objet appelé newData
et de le remplir de structures de données avec de nouvelles données. Quand c'est fait, je viens de céder
private static volatile SystemData _allData
public static bool LoadAllSystemData()
{
SystemData newData = new SystemData();
/* fill newData with up-to-date data*/
...
_allData = newData.
}
Cela devrait fonctionner depuis la cession est atomique et les fils qui ont la référence à des données anciennes continuer à l'utiliser et le reste du nouveau système de données juste après la cession. Cependant, mon collegue a dit qu'au lieu d'utiliser volatile
mot-clé et simple affectation que je devrais utiliser InterLocked.Exchange
car il a dit que, sur certaines plateformes, il n'est pas garanti que la référence affectation est atomique. Par ailleurs: quand je déclare the _allData
champ volatile
la
Interlocked.Exchange<SystemData>(ref _allData, newData);
produit l'avertissement "une référence à un champ volatile ne seront pas traités comme volatile" Que dois-je penser de cela?
Vous devez vous connecter pour publier un commentaire.
Il y a de nombreuses questions ici. De les examiner un à un moment:
De référence affectation est atomique. Interloqué.L'échange ne fait pas seulement référence de la mission. Il fait une lecture de la valeur actuelle d'une variable, caches loin l'ancienne valeur, et affecte la nouvelle valeur à la variable, tout comme une opération atomique.
Pas. Référence affectation est garanti d'être atomique sur tous .NET plates-formes.
Pas nécessairement. Votre collègue pourrait vous donner de bons conseils pour les mauvaises raisons. Peut-être il ya une autre raison pourquoi vous devriez être à l'aide de Contrefil.Exchange. Sans verrouillage de la programmation est incroyablement difficile, et le moment où vous partez de pratiques bien établies, épousée par des experts dans le domaine, vous êtes hors de la mauvaises herbes et de risquer le pire genre de conditions de course. Je ne suis ni un expert dans ce domaine ni un expert sur votre code, donc je ne peux pas faire un jugement, d'une manière ou l'autre.
Vous devriez comprendre pourquoi c'est un problème général. Qui mènera à une compréhension des raisons pour lesquelles l'avertissement est sans importance dans ce cas particulier.
La raison que le compilateur donne cet avertissement, c'est parce que le marquage d'un champ, alors que la volatilité signifie "ce champ va être mise à jour sur plusieurs threads-ne pas générer un code qui met en cache les valeurs de ce champ, et assurez-vous que toute lecture ou de l'écriture de ce champ ne sont pas "déplacé en avant et en arrière dans le temps" par l'intermédiaire de cache du processeur incohérences."
(Je suppose que vous comprenez déjà tout ça. Si vous n'avez pas une compréhension détaillée de la signification de la volatilité et de son impact sur le cache du processeur sémantique, alors vous ne pouvez pas comprendre comment il fonctionne et ne doit pas être à l'aide de volatiles. Sans verrouillage des programmes sont très difficiles à obtenir; assurez-vous que votre programme est bon, parce que vous comprenez comment cela fonctionne, pas de droit par accident.)
Maintenant, supposons que vous faites une variable qui est un alias de champ volatile par le passage d'une référence à ce champ. À l'intérieur de la méthode appelée, le compilateur n'a pas de raison que ce soit, à savoir que la référence doit avoir de la volatilité de la sémantique! Le compilateur va gaiement générer du code pour la méthode qui ne parvient pas à mettre en œuvre les règles de la volatilité des champs, mais la variable est un champ volatile. Qui peut complètement détruire vos sans verrouillage de la logique; l'hypothèse est toujours celle d'un champ volatile est toujours accéder à la volatilité de la sémantique. Il ne fait aucun sens de la traiter comme volatile et parfois pas d'autres fois, vous avez pour toujours être cohérente, sinon vous ne pouvez pas garantir la cohérence sur les autres accès.
Par conséquent, le compilateur avertit lorsque vous faites cela, parce que c'est probablement va complètement ruiner votre soigneusement élaboré sans verrouillage logique.
Bien sûr, Interloqué.L'échange est écrites pour s'attendre à un champ volatile et faire la bonne chose. L'avertissement est donc trompeuse. Je le regrette beaucoup; ce que nous avons fait est de mettre en œuvre un mécanisme par lequel l'auteur d'une méthode comme Interloqué.L'échange pourrait mettre un attribut sur la méthode en disant: "cette méthode qui prend un ref applique volatile de la sémantique sur la variable, donc supprimer l'avertissement". Peut-être dans une future version du compilateur que nous le ferons.
var myresult = await Task.Factory.CreateNew(() => MyWork(exclusivelyLocalStuffOrValueTypeOrCopy));
.Soit votre collègue se trompe, ou qu'il sait quelque chose que la spécification du langage C# ne fonctionne pas.
5.5 l'Atomicité des références à des variables:
Vous pouvez écrire à la volatilité de référence sans risque de contracter une valeur endommagée.
Vous devez bien sûr être prudent avec la façon 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 fait que.
Interloqué.Bourse< T >
Changements et renvoie la valeur d'origine, c'est inutile parce que vous ne voulez le changer et, comme Guffa dit, c'est déjà atomique.
À moins d'un profiler comme prouvé à être un goulot d'étranglement dans votre application, vous devriez envisager de unsing de serrures, il est plus facile de comprendre et de prouver que votre code est bon.
Iterlocked.Exchange()
n'est pas seulement atomique, elle prend également soin de mémoire visibilité:Synchronisation et Multiprocesseur Questions
Cela signifie que, en plus de l'atomicité il s'assure que: