7
votes

Pourquoi Interlocked.careExchange ne prend-il que les types de référence?

Disclaimer: mes messages sont apparemment toujours verbeux. Si vous connaissez la réponse à la question du titre, n'hésitez pas à simplement y répondre sans lire ma discussion prolongée ci-dessous.


le system.threading.Interlocked.Interlocked. / code> classe fournit Quelques méthodes très utiles pour aider à la rédaction du code de la sécurité thread-Safe. L'une des méthodes les plus complexes est comparaisonxchange , qui peut être utilisée pour calculer un total exécutant pouvant être mis à jour à partir de plusieurs threads.

puisque l'utilisation de comparaitxchange est un peu délicat, je pensais qu'une idée assez courante de fournir des méthodes d'assistance pour cela: xxx

MAINTENANT, je suis peut-être coupable d'être générique heureux (je vais admettre que cela est souvent vrai); mais il se sent stupide pour moi pour limiter la fonctionnalité fournie par les méthodes ci-dessus sur Double Valeurs uniquement (ou, plus précisément, pour que je dois écrire des versions surchargées de la Les méthodes ci-dessus pour chaque type que je souhaite supporter). Pourquoi je ne peux pas faire cela? xxx

je ne peux pas faire cela car interlocked.compeeexchange apparemment a un T: Classe contrainte et Je ne comprends pas pourquoi . Je veux dire, peut-être c'est parce qu'il existe déjà des surcharges pour comparaisonxchange qui accepte int32 , int64 , double , etc.; Mais cela ne semble guère une bonne justification. Dans mon cas, par exemple, il serait tout à fait pratique de pouvoir utiliser la méthode agrégate pour effectuer une large gamme de calculs atomiques.


0 commentaires

3 Réponses :


-1
votes

Je soupçonnerais que interlocked.careeexchange effectue simplement un swap pointeur atomique sous la hotte.

essayer de le faire avec un type de valeur ne donnerait probablement pas aux résultats que vous attendez.

Vous pouvez, bien sûr, la valeur de la boîte type de la valeur dans un objet avant de les utiliser.


1 commentaires

Déversure la boxe des types de valeur comme objet serait pas travail, réellement. Voir mon premier commentaire à la réponse de Mehrdad.



12
votes

interlocked.careExchange est censé être implémenté avec des instructions atomiques indigènes fournies directement par le processeur. Il est inutile d'avoir quelque chose comme celui-ci Utiliser un verrouillage en interne (il est conçu pour les scénarios sans verrouillage).

Les processeurs qui fournissent à Atomic Comparer les instructions d'échange la supportent naturellement comme étant des opérations «de la taille d'un registre» (par exemple, la plus grande instruction de comparaison sur un processeur Intel X64 est CMPXCHG16B qui fonctionne sur des valeurs 128 bits ).

Un type de valeur arbitraire peut être potentiellement plus grand que cela et le comparer-l'échange de choses peut ne pas être possible avec une seule instruction. Comparer-l'échange d'un type de référence est facile. Quelle que soit sa taille totale en mémoire, vous comparez et copier un petit pointeur d'une taille connue. Ceci est également vrai pour les types primitifs tels que int32 et double - tous d'entre eux sont petits.


8 commentaires

Je pense que cela se concentra au centre de moi une fois que je l'ai lu dans la documentation MSDN peu après avoir posté la question (pour la surcharge accepte les paramètres objet ): "Les objets sont comparés pour l'égalité de référence, plutôt que < Code> Object.equals . En conséquence, deux instances en boîte du même type de valeur (par exemple, l'entier 3) semblent toujours être inégaux et aucune opération n'est effectuée. N'utilisez pas cette surcharge avec des types de valeur . " Bien sûr - il ne va pas utiliser la méthode égale , mais plutôt vérifier les références elles-mêmes.


Donc, clairement, mon seul choix serait d'écrire toutes ces méthodes surchargées moi-même (pour int , long , etc.) après tout - si je voulais vraiment aller aller cette route. À droite?


@Dan: Je ne sais pas comment vous le feriez pour un type de valeur plus grand atomiquement sans utiliser de verrouillage (code> (échange d'une bande de valeurs entières). Le point de comparer-échange est que c'est atomique; C'est-à-dire qu'il n'y aura pas de point à temps lorsque vous pouvez observer une partie de l'opération est effectué et l'autre partie n'est pas. Mettre un groupe de comparaison-échangers le long de l'autre ne contribuera pas à faire de l'opération globale atomique (chaque partie est atomique, mais l'opération dans son ensemble n'est pas).


@Dan: ignorer mon dernier commentaire. Votre avertissement m'a fait de ne pas lire votre question et j'ai mal compris ce que vous vouliez dire à partir d'une méthode surchargée;). Oui, vous devrez le faire.


@Mehrdad: Je pense que tu m'as perdu. Mon intention n'était pas d'utiliser "un groupe de comparaison-échangers le long de l'autre" ... plutôt de fournir un moyen facile d'effectuer n'importe quel type de Single Agrégation atomiquement (par exemple, en résumé des valeurs carrées) .


@Mehrdad: OK, ignore mon dernier commentaire .


@Dan: Oui. J'ai dit que juste avant votre commentaire. Vous devrez la mettre en œuvre spécifiquement pour int , long , ... soit en utilisant des surcharges ou en cochant typeof (t) et prenant un Piste de code alternatif. Vous ne pourrez pas faire cela avec un seul chemin de code.


Je me demande s'il y aurait eu une difficulté à fournir une paires structure où T1: classe où T2: classe {Public T1 F1; Publique T2 F2;} et fournissant une surcharge de comparaisonxchange pour cela, puisque les processeurs où ce type prendrait 64 bits comportant des instructions de comparaison de 64 bits et ceux où le type prendrait 128 bits ont des instructions de comparaison de 128 bits? Être capable d'échanger deux références à la fois serait plutôt pratique parfois.



1
votes

Parce que cette surcharge est spécifiquement destinée à comparer et à échanger une référence. Il n'effectue pas de vérification d'égalité à l'aide de la méthode Equals (). Étant donné qu'un type de valeur n'aurait jamais d'égalité de référence avec la valeur que vous comparez contre, je suppose que je suppose qu'ils sont contraints de la classe afin d'éviter toute utilisation abusive.


3 commentaires

Je parie que votre nom de famille vous donne beaucoup de crédit parmi vos collègues.


C'était un +1 de moi, au fait; Je n'étais pas serré.


Lol ça va, je ne l'ai pas pris comme tel. Très bonne question aussi au fait.