Domanda

Ho notato che puoi chiamare Queue.Synchronize per ottenere un oggetto coda thread-safe, ma lo stesso metodo non è disponibile su Queue < T > ;. Qualcuno sa perché? Sembra strano.

È stato utile?

Soluzione

Aggiorna : in .NET 4 ora è presente ConcurrentQueue<T> in System.Collections.Concurrent, come documentato qui http://msdn.microsoft.com/en-us/library/dd267265.aspx . È interessante notare che il suo metodo IsSynchronized (giustamente) restituisce false.

Interlocked.CompareExchange() è una riscrittura completa completa, la creazione di copie della coda da enumerare e l'utilizzo di tecniche avanzate di non blocco come Thread.SpinWait() e <=>.

Il resto di questa risposta è ancora rilevante nella misura in cui si riferisce alla scomparsa dei vecchi membri Synchronize () e SyncRoot e al perché non hanno funzionato molto bene dal punto di vista dell'API.


Secondo il commento di Zooba, il team BCL ha deciso che troppi sviluppatori stavano fraintendendo lo scopo di Synchronize (e, in misura minore, SyncRoot)

Brian Grunkemeyer lo ha descritto sul blog del team BCL un paio di anni fa: http://blogs.msdn.com/bclteam/archive/ 2005/03/15 / 396399.aspx

Il problema chiave è ottenere la granularità corretta attorno ai blocchi, dove alcuni sviluppatori usano ingenuamente più proprietà o metodi su una quot &; <<> sincronizzata; raccogliere e ritenere che il loro codice sia thread-safe. Brian usa Queue come suo esempio,

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

Gli sviluppatori non avrebbero capito che Count poteva essere cambiato da un altro thread prima che Dequeue fosse invocato.

Costringere gli sviluppatori a utilizzare un'istruzione di blocco esplicita per l'intera operazione significa prevenire questo falso senso di sicurezza.

Come accenna Brian, la rimozione di SyncRoot è stata in parte dovuta al fatto che era stata introdotta principalmente per supportare Synchronized, ma anche perché in molti casi esiste una scelta migliore di lock object - il più delle volte, sia l'istanza stessa della coda, oppure a

private static object lockObjForQueueOperations = new object();

sulla classe proprietaria dell'istanza della coda ...

Quest'ultimo approccio è generalmente più sicuro in quanto evita alcune altre trappole comuni:

Come si suol dire, threading è difficile e far sembrare semplice può essere pericoloso.

Altri suggerimenti

Potresti trovare il CTP parallelo da provare; ecco un post sul blog dei ragazzi che lo stanno mettendo insieme che è abbastanza attuale:

Enumerazione delle raccolte simultanee

Non è esattamente la stessa cosa, ma potrebbe risolvere il tuo problema più grande. (Usano persino Queue<T> contro ConcurrentQueue<T> come loro esempio.)

Ce n'è uno ora, in .Net 4.0:

ConcurrentQueue<T> 

in System.Collections.Concurrent

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

(Suppongo che intendi Coda < T > per il secondo.)

Non posso rispondere specificamente alla domanda, tranne per il fatto che le proprietà IsSynchronized e SyncRoot (ma non Synchronize () esplicitamente) sono ereditate dall'interfaccia ICollection. Nessuna delle raccolte generiche usa questo e ICollection & Lt; T & Gt; l'interfaccia non include SyncRoot.

Per quanto riguarda il motivo per cui non è incluso, posso solo ipotizzare che non fossero stati utilizzati né nel modo previsto dai progettisti della biblioteca o semplicemente non fossero stati usati abbastanza da giustificare il loro mantenimento nelle nuove collezioni.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top