2009-11-28 12 views
12

No estoy muy seguro, así que pensé en preguntar. ¿Eliminar y agregar elementos a un objeto System.Collections.Generic.List<> no sería seguro para subprocesos?Lista <T> eliminación y adición simultáneas

Mi situación:

Cuando se recibe una conexión, se añade a la lista, pero también, al mismo tiempo, hay un trabajador que está eliminando las conexiones muertas y tal.

¿Hay algún problema? ¿Lo hará un lock? También quiero saber si se me permite usar un bloqueo en el objeto de la lista con su método Foreach<>.

+0

Eche un vistazo a http://stackoverflow.com/questions/6601611/no-concurrentlistt-in-net-4-0 - la respuesta vale la pena leerla. –

Respuesta

28

Sí, agregar y eliminar elementos de un List<> no es seguro para subprocesos, por lo que debe sincronizar el acceso, por ejemplo, usando lock.

Tenga en cuenta que la palabra clave lock de ninguna manera bloquea el objeto que utiliza como identificador, solo evita que dos subprocesos entren en el mismo bloque de código al mismo tiempo. Necesitará bloqueos alrededor de todo el código que accede a la lista, usando como el mismo objeto como identificador.

+4

+1 Buena explicación. –

+0

¿Qué hay de eliminar tal en 'List.Foreach <>', ¿todavía requiere un bloqueo? – TheAJ

+0

@AJ: Sí, necesita un bloqueo de * todos * accesos a la lista. Si está recorriendo la lista y otro hilo elimina un elemento, obtendrá una excepción (o un bloqueo en algunas circunstancias). – Guffa

2

List<T> no es seguro para subprocesos, así que sí, tendrá que controlar el acceso a la lista con un candado. Si tienes varios hilos que acceden a la Lista, asegúrate de que los tienes respetando el bloqueo o tendrás problemas. La mejor manera de hacer esto sería subclasificar la Lista para que el bloqueo ocurra automáticamente, de lo contrario es muy probable que termine olvidando eventualmente.

+0

Esa no es la mejor manera. No se debe solo a la implementación de List, sino que su interfaz no está diseñada para ser utilizada por múltiples hilos. Si desea una forma segura de hacer subprocesos para hacer esto, también necesita una interfaz completamente diferente. La lista debe ser un detalle de implementación interna, bien oculto para los usuarios. http://blogs.msdn.com/jaredpar/archive/2009/02/11/why-are-thread-safe-collections-so-hard.aspx –

-1

En realidad, a veces Lista <> es seguro para subprocesos, ya veces no, de acuerdo con Microsoft:

miembros estáticos públicos de este tipo son seguros para subprocesos . No se garantiza que ningún miembro de instancia sea seguro para subprocesos.

pero esa página va a decir:

enumerar a través de una colección es intrínsecamente no es un procedimiento seguro para subprocesos . En el raro caso en que una enumeración contenga uno o más accesos de escritura , la única forma de garantizar la seguridad de subprocesos es bloquear la colección durante toda la enumeración . Para permitir el acceso a la colección por medio de múltiples hilos para leer y escribir, debe implementar su propia sincronización.

+4

No, una lista nunca es segura para subprocesos. Es solo un texto estándar utilizado para todas las clases regulares. Como la clase List no tiene ningún miembro estático, no hay miembros seguros para subprocesos. – Guffa

+0

Estoy de acuerdo en que definitivamente debería usar un candado. Gracias por la aclaración. – DOK

+1

@Guffa: Estoy bastante seguro de que 'List ' es seguro para subprocesos en presencia de varios lectores y cero escritores. Es bastante raro que las colecciones no sean seguras para subprocesos en presencia de múltiples lectores, ya que se presupone tal nivel de seguridad de subprocesos en ausencia de documentación; no obstante, las únicas colecciones que diría que son "nunca" seguras para subprocesos son cosas como colecciones flojas donde dos accesos simultáneos de "lectura" pueden causar modificaciones conflictivas. – supercat

-1

Definitivamente el uso de bloqueo para un código particular lo hace seguro para la ejecución de subprocesos, pero no estoy de acuerdo con él para el escenario actual.

Puede implementar el método Sincronizado para hacer seguro el hilo de recolección. Este link explica por qué y cómo hacerlo.

Otro enfoque puramente programático se menciona en este link, aunque nunca lo probé de primera mano, pero debería funcionar.

Por cierto, una de las mayores preocupaciones es que, ¿estás tratando de mantener algo así como el grupo de conexión por tu cuenta? Si es así, ¿por qué?

Respondo mi respuesta. Usando bloqueos en mejor respuesta que utilizando este método.

+0

Sincronizado fue una mala idea. Ver http://blogs.msdn.com/b/jaredpar/archive/2009/02/11/why-are-thread-safe-collections-so-hard.aspx –

+0

Subí porque "lo recuperaste" :) sin eliminar, lo que podrías haber hecho. Pero dejarlo allí podría ser perspicaz para otros. –

4

En el momento de la pregunta no fue .NET Framework 4 todavía, pero las personas que se enfrentan el problema ahora deben tratar de usar colecciones de System.Collections.Concurrent espacio de nombres para hacer frente a flujos seguros problemas

Cuestiones relacionadas