2009-04-02 15 views
8

Nel codice seguente:ContainsKey Discussione sicuro

public class StringCache 
{ 
    private readonly object lockobj = new object(); 

    private readonly Dictionary<int, string> cache = new Dictionary<int, string>(); 

    public string GetMemberInfo(int key) 
    { 
     if (cache.ContainsKey(key)) 
      return cache[key]; 
     lock (lockobj) 
     { 
      if (!cache.ContainsKey(key)) 
       cache[key] = GetString(key); 
     } 
     return cache[key]; 
    } 

    private static string GetString(int key) 
    { 
     return "Not Important"; 
    } 
} 

1) è thread ContainsKey sicuro? IOW, cosa succede se quel metodo è in esecuzione quando un altro thread sta aggiungendo qualcosa al dizionario? 2) Per la prima cache di ritorno [chiave], c'è qualche possibilità che possa restituire un valore alterato?

TIA,

MB

risposta

14

Il filo di sicurezza intrinseca di ContainsKey non importa, poiché non v'è alcuna sincronizzazione tra [tasto] ContainsKey & cache.

Ad esempio:

if (cache.ContainsKey(key)) 
    // Switch to another thread, which deletes the key. 
    return cache[key]; 

MSDN è abbastanza chiaro su questo punto:

per consentire la raccolta a cui accedere da più thread per la lettura e scrittura, è necessario implementare il proprio sincronizzazione.

Per ulteriori informazioni, JaredPar postato una grande voce di blog all'indirizzo http://blogs.msdn.com/jaredpar/archive/2009/02/11/why-are-thread-safe-collections-so-hard.aspx su collezioni thread-safe.

1

Qui è quello che dice nel MSDN documentation:

statici pubblici (Shared in Visual Basic) di questo tipo sono thread-safe. Non è garantito che tutti i membri di istanza siano thread-safe.

Un Dizionario < (Of < (TKey, TValue>)>) in grado di supportare più lettori simultaneamente, fino a quando la raccolta non viene modificato. Anche così, enumerare tramite una raccolta è intrinsecamente non una procedura thread-safe . Nel raro caso in cui un'enumerazione contenga gli accessi in scrittura , la raccolta deve essere bloccata durante l'intera enumerazione . Per consentire l'accesso alla raccolta da più thread per la lettura e la scrittura , è necessario implementare la propria sincronizzazione .

Se sto leggendo correttamente, non credo che sia sicuro.

5

No, ContainsKey non è thread-safe se si scrivono valori mentre si sta tentando di leggere.

Sì, c'è la possibilità di ottenere risultati non validi, ma probabilmente inizierai a vedere le eccezioni prima.

Dai un'occhiata a ReaderWriterLockSlim per il blocco in situazioni come questa: è stato creato per fare questo genere di cose.

1

Il dizionario non è thread-safe.

se dici che

cosa succede se questo metodo è in esecuzione quando un altro thread è aggiungendo qualcosa al dizionario?

quindi suppongo che altre funzioni accedano allo cache pure. È necessario sincronizzare gli accessi (lettura e scrittura) allo cache. Usa il tuo oggetto di blocco in tutte queste operazioni.