7
votes

Pourquoi est-ce que ConcurrentWhatTerver.count prend un instantané?

sur C # /. NET Little Wonders Article pour ConcurrentStack / Queue simultanée , ce qui suit est mentionné concernant le .Count Opération sur le ConcurrentStack : < / p>

Compte prend un instantané de la pile puis compte les articles. Ça signifie C'est une opération O (n), si vous venez de Voulez-vous vérifier une pile vide, appelez Isempty à la place qui est O (1).

Je ne suis pas mal expérimenté dans la programmation multi-threadé, mais je comprends pourquoi vous ne pouvez pas simplement faire boucler les éléments de la collection et les compter, car la collection peut changer par d'autres threads en même temps. Cependant, si vous devez verrouiller le ConcurrentStack suffisamment longtemps pour faire un instantané, ne serait-il pas plus facile de compter les éléments pendant que vous l'avez enfermé, retourner cela et relâchez la serrure, et libérez la serrure. de prendre les frais généraux et le coût temporel de générer un instantané entier avant de libérer la serrure?

Je manque peut-être quelque chose de base sur la façon dont cela fonctionne et j'apprécierais toute pensée ou opinion que vous pourriez avoir.


0 commentaires

5 Réponses :


4
votes

Je ne sais pas avec certitude, mais voici une supposition.

La pile pourrait être implémentée comme une liste individuelle, composée de cellules immuables , dans lesquelles chaque cellule pointe vers la cellule sous la pile. Ensuite, un "instantané" serait simplement de faire une copie du sommet de la pile; Parce que les cellules sont immuables, cela tire également le long du reste de la pile de courant.

Ainsi, l'instantané serait une opération O (1), mais compter les éléments réels est toujours O (n).


1 commentaires

Merci, ça a du sens. J'avais supposé que l'instantané était également une opération O (n).



3
votes

Vous supposez que pour compter sur un instantané, il doit ressortir une grande serrure.

I Croyez Les collections simultanées sont conçues avec peu coûteuse - éventuellement optimiste - instantané à l'esprit. Par exemple, si vous ithétiez sur un ConcurrentStack via getenumerator () , qui utilise également un instantané. Je doute vivement que c'est toujours une opération O (n) de créer cet instantané.


1 commentaires

Ya, ça a du sens. Je suppose que lorsque je pense que l'instantané, je pense "copier", mais c'est plus juste une vue statique garantie des données.



5
votes

Je ne sais pas si cela est implémenté comme ça, mais si vous l'implémentez comme une liste liée à des nœuds immuables, un instantané est presque libre et ne nécessite aucune verrouillage. Vous venez d'obtenir l'élément supérieur actuel. Puis suivez la liste liée au début.

Vous pouvez enregistrer la position de chaque nœud sur la pile du nœud, mais celle-ci échangez une mémoire pour la performance du nombre . Et probablement compter ne s'appelle pas assez couramment pour garantir cette mémoire supplémentaire par nœud.

Travail le plus concurrentcollection sans serrures du tout. Une telle pile soutenue de liste liée pourrait par exemple être construite à l'aide de interlocked.careexchange sur le champ pointant sur le nœud actuel. Et si vous faites des opérations sans verrouillage, vous devez généralement les faire sans pareil, car les opérations sans verrouillage ne respecteront pas la serrure.


0 commentaires

1
votes

Je suppose que la plus grande raison est que poser une file d'attente simultanée (où deux ou plusieurs threads manipulent toujours le contenu) pour un nombre d'articles est un concept imparfait pour commencer. Je soupçonne qu'ils n'ont fourni que la propriété de comptage pour se conformer aux interfaces existantes. Donc, si la seule raison d'une API d'exister est de respecter une exigence d'interface, alors qui se soucie de la manière dont il fonctionne comme vous ne devriez pas l'utiliser pour commencer.

Lorsque vous travaillez avec des objets modifiés par plusieurs threads, il n'est jamais correct de demander à l'objet de l'état / valeur que l'autre thread peut changer. Depuis au moment où votre question est répondue, cela peut ne plus être la bonne réponse. Cela s'apparente au problème fondamental de la propriété "invoquée" de Winform. Certaines API ne sont qu'une mauvaise idée dans un environnement multi-fileté et je pense que ce nombre tombe dans cette catégorie.

En fin de compte, il est un peu étrange que les impléments n'utilisaient pas un membre d'interface explicite pour la propriété ICollection.Count plutôt que de le rendre public. Ensuite, au moins vous savez que vous ne devriez pas l'utiliser. Ils ont spécifié pour utiliser ISPTY sur MSDN; Cependant, il est facile de négliger ça.


1 commentaires

Parfois, vous voulez vraiment compter , dites-lui de faire rapport sur l'avancement de la collecte de tâches. Comme les autres affiches mentionnent, la propriété est réellement assez efficace, j'ai mal compris ce que cela signifie prendre un instantané.



-1
votes

ConcurrentStack et Concurrentqueur sont des collections de sécurité de fil, donc aucun verrouillage n'est impliqué. Dans la concurrence, par exemple, le nombre est calculé en lisant le nœud de tête puis traverser la liste d'accumulation du compte


0 commentaires