Question

J'ai remarqué que vous pouvez appeler Queue.Synchronize pour obtenir un objet de file d'attente thread-safe, mais la même méthode n'est pas disponible sur Queue < T > ;. Quelqu'un sait-il pourquoi? Cela semble un peu bizarre.

Était-ce utile?

La solution

Mettre à jour : dans .NET 4, il existe maintenant ConcurrentQueue<T> dans System.Collections.Concurrent, comme indiqué ici http://msdn.microsoft.com/en-us/library/dd267265.aspx . Il est intéressant de noter que sa méthode IsSynchronized (à juste titre) renvoie false.

Interlocked.CompareExchange() est une réécriture complète au sol, créant des copies de la file d'attente à énumérer et utilisant des techniques avancées de verrouillage sans verrouillage telles que Thread.SpinWait() et <=>.

Le reste de cette réponse est toujours d'actualité dans la mesure où il est lié à la disparition des anciens membres Synchronize () et SyncRoot et aux raisons pour lesquelles ils ne fonctionnaient pas très bien du point de vue des API.

Selon le commentaire de Zooba, l'équipe de la BCL a décidé que trop de développeurs avaient mal compris l'objectif de Synchronize (et dans une moindre mesure, SyncRoot)

Brian Grunkemeyer a décrit cela sur le blog de l'équipe de la BCL il y a quelques années: http://blogs.msdn.com/bclteam/archive/ 2005/03/15 / 396399.aspx

Le problème essentiel est d'obtenir la granularité correcte autour des verrous, où certains développeurs utiliseraient naïvement plusieurs propriétés ou méthodes sur un & "synchronized &"; collection et croire que leur code est thread-safe. Brian utilise Queue comme exemple,

if (queue.Count > 0) {
    object obj = null;
    try {
        obj = queue.Dequeue();

Les développeurs ne se rendraient pas compte que Count pourrait être modifié par un autre thread avant l'appel de Dequeue.

Forcer les développeurs à utiliser une instruction de verrouillage explicite sur l'ensemble de l'opération signifie empêcher ce faux sentiment de sécurité.

Comme Brian le mentionne, la suppression de SyncRoot s’explique en partie par le fait qu’il a été principalement introduit pour prendre en charge Synchronized, mais aussi parce que, dans de nombreux cas, le choix de l’objet verrou est plus judicieux - la plupart du temps, l’instance de file d’attente elle-même ou un

private static object lockObjForQueueOperations = new object();

sur la classe possédant l'instance de la file d'attente ...

Cette dernière approche est généralement la plus sûre car elle évite certains autres pièges courants:

Comme on dit, threading est difficile , et donner l'impression que cela semble facile peut être dangereux.

Autres conseils

Vous trouverez peut-être que le CTP parallèle vaut la peine d’être vérifié; voici une entrée de blog des gars qui le mettent ensemble qui est assez d'actualité:

Énumération des collections simultanées

Ce n'est pas tout à fait la même chose, mais cela pourrait résoudre votre plus gros problème. (Ils utilisent même Queue<T> contre ConcurrentQueue<T> comme exemple.)

Il y en a un maintenant en .Net 4.0:

ConcurrentQueue<T> 

dans System.Collections.Concurrent

http://msdn.microsoft.com/en-us/library/ dd267265.aspx

(Je suppose que vous voulez dire Queue < T > pour le second.)

Je ne peux pas répondre spécifiquement à la question, si ce n'est que les propriétés IsSynchronized et SyncRoot (mais pas Synchronize () explicitement) sont héritées de l'interface ICollection. Aucune des collections génériques n'utilise ceci et la collection ICollection & Lt; T & Gt; l’interface n'inclut pas SyncRoot.

En ce qui concerne la raison pour laquelle il n’est pas inclus, je ne peux que spéculer sur le fait qu’ils n’ont pas été utilisés de la manière prévue par les concepteurs de bibliothèques ou n’ont tout simplement pas été utilisés suffisamment pour justifier de les conserver dans les nouvelles collections.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top