10

Attualmente sto scrivendo un'applicazione C#. Sono nuovo nell'usare un ConcurrentDictionary quindi ho alcune domande sulla sicurezza del thread. In primo luogo, questo è il mio dizionario:alcune domande sull'uso di ConcurrentDictionary

/// <summary> 
    /// A dictionary of all the tasks scheduled 
    /// </summary> 
    private ConcurrentDictionary<string, ITask> tasks; 

ho un'istanza di questo nella mia classe e utilizzarlo per tenere traccia di tutti i miei oggetti che implementano ITask. Voglio assicurarmi che il mio setup funzioni correttamente in un ambiente multi-thread.

Se più thread desiderano ottenere il conteggio del numero di elementi in ConcurrentDictionary, è necessario bloccarlo?

Se voglio ottenere una chiave particolare dal dizionario, ottenere l'oggetto di quella chiave e chiamare un metodo su di esso, devo bloccarlo? ad esempio:

/// <summary> 
    /// Runs a specific task. 
    /// </summary> 
    /// <param name="name">Task name.</param> 
    public void Run(string name) 
    { 
     lock (this.syncObject) 
     { 
      var task = this.tasks[name] as ITask; 
      if (task != null) 
      { 
       task.Execute(); 
      } 
     } 
    } 

Mantenere la mente più thread possono chiamare il metodo Run cercando di chiamare il metodo Execute ITask. Il mio obiettivo è quello di avere tutto il thread sicuro e il più performante possibile.

risposta

9

I metodi e le proprietà della ConcurrentDictionary themself sono completamente thread sicura:

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

rappresenta una raccolta thread-safe di coppie di valori-chiave che può essere accessibile da più thread contemporaneamente.

Questa include la proprietà Count:

Conte ha la semantica di snapshot e rappresenta il numero di elementi nella ConcurrentDictionary nel momento in cui il conte era accesso.

Tuttavia ciò non significa che gli oggetti tenuti all'interno del dizionario sono essi stessi thread-safe. Cioè, non c'è nulla che impedisca a due thread di accedere allo stesso oggetto Task e provare ad eseguire il metodo Execute su di esso.Se desideri serializzato (bloccato) l'accesso a ogni singola attività per il metodo Execute, allora vi consiglio avendo un oggetto di blocco all'interno Task e bloccaggio durante l'esecuzione Execute:

public class Task 
{ 
    private object _locker = new object(); 

    public void Execute() 
    { 
     lock (_locker) { 
      // code here 
     } 
    } 
} 

Ciò assicura che almeno ogni singola attività doesn avere più thread in esecuzione Execute. Immagino che questo sia ciò che cerchi dal contesto della domanda e dai nomi delle classi e dei metodi.

+0

è il thread di proprietà '.count' sicuro? o il metodo '.Count()'? Qual è la differenza? – Zapnologica

2

Tutti i metodi di ConcurrentDictionary possono essere chiamati da più thread.

Non garantisce che altre parti del programma non necessitino di sincronizzazione in quanto potrebbe essere necessario utilizzare i blocchi per accedere ad altri oggetti/oggetti multipli contemporaneamente.

I.e. il codice di esempio si blocca sia per il recupero di un'attività che per l'esecuzione. Mostra un esempio di blocco per accedere a più oggetti atomicamente.

Nota a margine: è necessario controllare il blocco per task.Execute() poiché impedisce ad altri thread di eseguire attività in parallelo. Potrebbe essere quello che vuoi ottenere, ma in questo caso l'uso di ConcurrentDictionary potrebbe essere eccessivo.

Problemi correlati