¿Puedo, sin bloqueo, llamar de manera segura a List.AddRange (r) desde varios subprocesos? Si no, ¿con qué tipo de problema me encontraría?¿Es seguro el subproceso de la lista <T> .AddRange()?
Respuesta
No, its documentation no dice que es seguro para subprocesos, por lo tanto, no lo es.
Público estático (compartido en Visual Basic) miembros de este tipo son seguros para subprocesos. Cualquier miembro de instancia no es garantizado para ser seguro para subprocesos.
En cuanto a lo que puede salir mal, piensa en lo AddRange (newitems) hace:
- Comprobar si hay suficiente espacio en la matriz interna
- Si no es así:
- Asignar una nueva matriz
- Copie los elementos actuales a la nueva matriz
- Establezca un campo para apuntar al nuevo arr ay
- Copiar los newitems al local correcta en la matriz interna
- actualización de la “cuenta” de campo (esto se utiliza para controlar donde se inserta el siguiente punto)
Ahora piensa en lo que se sucede si lo anterior está mezclado con otra llamada a AddRange() o incluso solo una llamada para leer un elemento.
No, no es seguro para subprocesos.
El hilo A podría llamar a AddRange en su lista. Podría iterar parcialmente sobre la colección y cambiar los hilos.
El hilo B podría llamar Agregar/Quitar, etc. antes de que el hilo A haya finalizado.
No, no es así, pero me gustaría agregar que es más eficiente hacer un myList.AddRange(...);
dentro de un bloqueo que haciendo varios lock (syncLock) { myList.Add(...) };
.
¿Con qué tipo de problema se encontraría? Cuando un hilo está agregando un elemento mientras que otro está enumerando la lista, List<T>
arrojará una cierta excepción porque hace algunas versiones internas, ya que quiere evitar que nosotros, los desarrolladores pobres, peguemos con desagradables efectos secundarios.
También el List<T>
mantiene internamente una matriz en la que almacena sus elementos. Tal vez establecer un elemento en una matriz sea bastante atómico, pero cada vez que se alcance la capacidad de esta matriz, se creará una nueva y los elementos se copiarán de la anterior. Entonces, cuando un hilo desea agregar algo mientras se realiza esa copia, puede imaginarse que las cosas se desincronizarán.
Excelente respuesta, gracias. =) –
Hasta .NET Framework 4.0, ninguna colección .NET es segura para subprocesos. A continuación, se le pedirá que lo bloquee antes de acceder a él en su código
Collections and Synchronization (Thread Safety)
.
Por otro lado, .NET Framework 4.0 introduce el nuevo espacio de nombre System.Collections.Concurrent
que incluye Thread-Safe Collections
de grano fino.
Finalmente, si puede usar .NET Framework 4.0, le recomiendo que lo haga para lo que necesita; de lo contrario, asegúrese de bloquear la colección cada vez que quiera modificarla o acceder a ella.
Además, una colección estática debe ser segura para subprocesos, pero tenga cuidado, ya que no se garantiza que los miembros sean.
editar # 1
Después de comprobaciones adicionales debido al comentario de Steve Townsend, admito que hay tres colecciones compatibles con el proceso dentro del marco .NET partir de la versión 3.0:
- SynchronizedCollection Generic Class;
- SynchronizedKeyedCollection Generic Class;
- SynchronizedReadOnlyCollection Generic Class.
Disculpe, acabo de aprender su extenuación yo mismo. =)
no es cierto, hay algunos en 'System.Collections.Generic' que funcionan aquí y son anteriores a 4.0 –
@Steve Townsend: Después de la verificación, tienes razón, estoy equivocado. Además, la colección genérica 'IList
No hay problema. Te debo un +1 por mencionar las 4.0 colecciones. –
Dependiendo de su uso, SynchronizedCollection podría funcionar.
No tendría un solo disparo AddRange
sin embargo. Si solo está utilizando esto para inicializar la colección, puede hacerlo ya que hay una sobrecarga de constructor IEnumerable
.
+1 ¡Acabo de aprender algo nuevo hoy! ¡Gracias! =) –
Gracias por su voto positivo. Me gustaría hacerle saber que he editado mi respuesta para reflejar esta nueva información que me brindó (a todos nosotros). –
- 1. LISTA <> AddRange tirar ArgumentException
- 2. ¿Es seguro el subproceso java.util.Hashtable?
- 3. ¿Es seguro el subproceso java.sql.Connection?
- 4. ¿Es seguro el subproceso SecurityContextHolder?
- 5. ¿Es seguro el subproceso java.lang.reflect.Method?
- 6. ¿Es seguro el subproceso DocumentBuilder.parse()?
- 7. ¿El subproceso console.writeline es seguro?
- 8. ¿Es seguro el subproceso Joiner?
- 9. ¿Es seguro este subproceso?
- 10. En Delphi, ¿es seguro el subproceso TDataSet?
- 11. En Delphi, ¿es seguro el subproceso OutputDebugString?
- 12. ¿El subproceso java.util.Calendar es seguro o no?
- 13. ¿es seguro el subproceso java.util? USID?
- 14. ¿Es seguro el subproceso JMS QueueSender?
- 15. ¿Es seguro el subproceso GHashTable (glib2)?
- 16. C# LINQ `Lista <Interface> .AddRange` método no funciona
- 17. Lista <IJob> .AddRange (Lista <Job>) No funciona
- 18. ¿Está seguro el subproceso RNGCryptoServiceProvider.GetBytes?
- 19. .NET - ¿Es seguro el subproceso de método Queue.Enqueue?
- 20. ¿El subproceso del método de extensión es seguro?
- 21. Java: seguro de subproceso RandomAccessFile
- 22. En WPF, ¿el subproceso UI dispatcher.begininvoke es seguro?
- 23. Delphi - ¿Está seguro el subproceso TClientDataset?
- 24. .NET List <T> Concat vs AddRange
- 25. ¿Es seguro este subproceso de llamada de cliente JAX-WS?
- 26. ¿Es seguro un subproceso PrintWriter de socket Java?
- 27. ¿El subproceso Bloque de la aplicación de registro de Microsoft Enterprise Library 5.0 es seguro?
- 28. ¿Es seguro el subproceso de la clase Java MessageFormat? (a diferencia de SimpleDateFormat)
- 29. ¿Está seguro el subproceso de SQLite en esta situación?
- 30. AddRange en una colección
btw - re '¿qué tipo de problema?' - es probable que obtenga una Excepción, en algún momento al azar cuando varios hilos entran en conflicto –