10

Actualmente estoy escribiendo una aplicación C#. Soy nuevo en el uso de ConcurrentDictionary así que tengo algunas preguntas sobre la seguridad de su hilo. En primer lugar, este es mi diccionario:algunas preguntas sobre el uso de ConcurrentDictionary

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

que ejecutar este en mi clase y utilizarlo para realizar un seguimiento de todos mis objetos que implementan ITask. Quiero asegurarme de que mi configuración funcione correctamente en un entorno de múltiples hilos.

Si varios subprocesos desean obtener el recuento de la cantidad de elementos en el ConcurrentDictionary, ¿debo bloquearlo?

Si quiero obtener una clave en particular del diccionario, obtengo el objeto de esa clave y llamo un método, ¿debo bloquearla? por ejemplo:

/// <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(); 
      } 
     } 
    } 

Guardando la mente, múltiples hilos podrían llamar al método Run buscando llamar al método Execute de ITask. Mi objetivo es que todo sea seguro y lo más eficiente posible.

Respuesta

9

Los métodos y propiedades de la ConcurrentDictionary sí mismos están completamente hilo de seguridad:

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

representa una colección thread-safe de pares de valores clave que pueden ser visitada por múltiples hilos simultáneamente.

Esto incluye la propiedad Count:

Conde tiene una semántica de instantáneas y representa el número de elementos en la ConcurrentDictionary en el momento cuando el conde era visitada.

Sin embargo esto no quiere decir que los objetos contenidos dentro del diccionario son ellos mismos hilo de seguridad. Es decir, no hay nada que impida que dos subprocesos accedan al mismo objeto Task e intenten ejecutar el método Execute en él.Si le gustaría serializado de acceso (bloqueo) a cada tarea individual para el método Execute, entonces yo sugeriría tener un bloqueo de objetos en el interior Task y de bloqueo cuando se ejecuta Execute:

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

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

Esto asegura que por lo menos cada tarea individual doesn no tienen múltiples hilos ejecutando Execute. Supongo que esto es lo que buscas del contexto de la pregunta y los nombres de las clases y métodos.

+0

es el hilo de la propiedad '.count' seguro? o el método '.Count()'? ¿Cuál es la diferencia? – Zapnologica

2

Todos los métodos de ConcurrentDictionary se pueden llamar sin peligro desde varios subprocesos.

No garantiza que otras partes de su programa no necesiten sincronización, ya que es posible que necesite usar bloqueos para acceder a otros objetos/objetos múltiples al mismo tiempo.

I.e. su código de muestra se bloquea tanto para recuperar una tarea como para ejecutarla. Muestra un ejemplo de bloqueo para acceder a objetos múltiples de forma atómica.

Nota al margen: debe revisar su bloqueo para task.Execute(), ya que prohíbe que otros subprocesos ejecuten tareas en paralelo. Puede ser lo que desea lograr, pero en este caso, usar ConcurrentDictionary puede ser excesivo.

Cuestiones relacionadas