2011-09-06 5 views
6

Tengo un NSMutableArray que contiene muchos objetos.¿Qué ocurre si NSMutableArray se modifica mediante varios subprocesos al mismo tiempo? (si los objetos que contiene se conservan en otro lugar)

Qué sucede si se realiza un cambio en la matriz, mientras estoy haciendo una copia de la matriz usando [NSMutableArray arrayWithArray: someArray];

P. ej .: si un objeto es eliminado de la matriz mientras se realiza la copia.

No estoy seguro de cómo probar este escenario.

EDITAR: Los objetos no se liberan (ya que se conservan en otro lugar). Solo uso esta matriz como una tabla de búsqueda.

+0

Tuve un problema similar hace dos días, pero estaba eliminando elementos de una matriz y enumerando en otra. Obtuve una excepción sobre la matriz que se está modificando. Si arrayWithArray: usa enumeración rápida (no lo sé) arrojará una excepción. –

+0

¡Creo que entiendes mi problema! Estoy tratando de determinar si se lanzará una excepción. Pero no puedo crear una prueba para verificar esto porque no puedo coordinar otra secuencia para modificar la matriz mientras se realiza una copia. – xcoder

Respuesta

11

como usted sabe, el contenedor/colección no se garantiza que sea seguro para subprocesos. ¿Qué podría suceder si cambia la matriz al copiar o leer? un montón de cosas. los casos obvios son que puede estar reasignando en el momento, puede pasar o devolver una referencia no válida (por ejemplo, la más reciente eliminado), o puede acceder a los objetos que han sido liberados (desde otro hilo). Además de las cosas que harán que su aplicación se bloquee o cause otro UB, es posible que no devuelva valores correctos o consistentes. es una mala interpretación de los datos. ninguno es bueno

usted no prueba el escenario - los problemas de enhebrado son difíciles de reproducir y realmente nunca puede cubrir todos los casos. dado que el objeto en sí mismo no garantiza la seguridad del hilo: su implementación tiene que restringir los accesos/mutaciones/interacciones a un hilo a la vez. al tratar con objetos que se utilizan en contextos de multiproceso: cada vez que accede o consulta información del estado mutable de un objeto, debe proteger el objeto (por ejemplo, con un bloqueo). por lo tanto, simplemente lo bloquea mientras lo usa. bloquear/copiar/desbloquear/usar la copia también es común. para un NSMutableArray, ejemplos de estado mutable serían todos sus objetos y su conteo. sus operaciones y mutaciones también usan el estado mutable del objeto, por lo que están restringidas.

si solo utiliza este objeto de un hilo, obviamente no es necesario que lo bloquee. esta es también una razón por la que pasar por copiar y mantener variantes inmutables son ambas buenas ideas en la mayoría de los casos.no necesita un candado para cada objeto, un protector para el objeto que lo sujeta es a menudo una buena forma de diseñar una clase para la seguridad del hilo.

actualización

... ¿Qué ocurre? ¿La copia contiene los 5 objetos (ya que se conservan en otras partes de todos modos? ¿Contienen 4? (Aun que contiene 4 es suficiente para mí) es una excepción lanzada?

si no se ha guardado correctamente la colección, es . tan bueno como un comportamiento indefinido y tiene suerte si se bloquea

es necesario tomar las precauciones adecuadas para evitar un comportamiento no definido su programa está funcionando en ese dominio cuando no está adecuadamente protegidas

dar más detalles..: retener los objetos externamente solo reduce la probabilidad de un comportamiento indefinido \ ior, pero ciertamente no lo elimina. Los ejemplos de consecuencias incluyen excepciones, segmentaciones seguras, lectura o escritura de memoria que se usa como otra asignación activa (que puede aparecer como un problema muy misterioso que también puede ser virtualmente imposible de reproducir).

Lo aliento a protegerse adecuadamente o tomar otro enfoque. UB es MALO :)

+0

Como los objetos no están siendo liberados por ningún hilo, estoy intentando comprender qué sucede si se modifica una matriz mientras se ejecuta [NSMutableArray arrayWithArray: (NSMutableArray *)]. Por ejemplo: 1. Si tengo una matriz que tiene 5 objetos (retenida también en otros lugares). 2. Otro hilo intenta hacer una copia de esta matriz. 3. Un tercer hilo modifica el conjunto original (elimina un objeto). 4. ¿Qué pasa? ¿La copia contiene los 5 objetos (ya que se conservan en cualquier otro lugar? ¿Contienen 4? (Incluso contiene 4 es suficiente para mí) ¿Se ha lanzado una excepción? – xcoder

+0

@xcoder updated – justin

+1

Lástima que no puedo volver a votar por el _undefined el comportamiento es evil_ update. –

5

de Apple de Docs:

objetos mutables son por lo general no apta para subprocesos. Para usar objetos mutables en una aplicación de subprocesos, la aplicación debe sincronizar el acceso a ellos mediante bloqueos. (Para obtener más información, consulte "Operaciones atómicas"). En general, las clases de colección (por ejemplo, NSMutableArray, NSMutableDictionary) no son seguras para subprocesos cuando se trata de mutaciones. Es decir, si uno o más subprocesos están cambiando la misma matriz, pueden surgir problemas. Debe bloquear los lugares donde se realizan las lecturas y escrituras para garantizar la seguridad del hilo.

También a partir de Apple Docs:

Aunque “atómica” significa que el acceso a la propiedad es seguro para subprocesos, simplemente haciendo todas las propiedades de su clase atómica no significa que su clase o de forma más general, su gráfico de objetos es "thread-safe" -thread safety no se puede expresar en el nivel de métodos de acceso individuales. Para obtener más información sobre el multihilo, vea Threading Programming Guide.

+0

He leído los documentos de Apple, pero no está claro para mí qué sucede realmente en este escenario. Como es difícil hacer que los dos hilos realicen las operaciones en sincronización, no puedo ver qué problema ocurrirá. – xcoder

+0

Consulte la sección: "Uso de la directiva @synchronized" en la guía de programación de enhebrado. También vea esta respuesta: http://stackoverflow.com/questions/3521190/synchronizing-nsmutablearray-for-thread-security – sosborn

+0

Sé para qué se usa @synchronized. La guía habla sobre cosas malas que pueden suceder cuando un objeto al que se accede por un hilo, se libera por otro hilo. Como ninguno de los subprocesos está liberando mis objetos, ¿qué sucede si una matriz que contiene referencias a un objeto se modifica mientras se realiza una copia? No creo que haya un escenario de "puntero colgante", porque los objetos mismos se conservan en otro lugar, por lo que cualquier puntero que apunte al objeto debería ser válido. ¿Qué le sucede a esta matriz, si se modifica cuando se realiza una copia? – xcoder

0

Si se llama removeObject al mismo tiempo que arrayWithArray, su programa se bloqueará. Si utiliza la sincronización, forzando a eliminarObject a realizarse ya sea justo antes o justo después de arrayWithArray, no puede saber cuántos objetos tendrá la nueva matriz. Eso no se bloqueará de inmediato, pero ¿qué va a hacer tu código? Tienes que tener muy claro que el resultado de [NSArray arrayWithArray: someArray] es una matriz que no contiene el contenido de someArray en este momento, sino el contenido de someArray en algún momento del pasado.

Cuestiones relacionadas