ios - Propiedades atómicas vs hilo-seguro en Objective-C
multithreading thread-safety (5)
En la mayoría de las discusiones que he leído, indica que hacer que una propiedad sea atómica no garantiza que sea segura para subprocesos, solo garantiza que el valor devuelto no será basura como resultado de un objeto escrito en él y otro tratando de leerlo al mismo tiempo.
Entiendo que esto no es seguro para subprocesos, ya que un tercer objeto podría escribirlo y, si bien el objeto que accede a él no se recuperaría, no es del todo seguro qué valor recuperará ya que varios objetos le escriben al mismo tiempo. Tiempo, y puede obtener cualquiera de sus valores.
Entonces, cuando decimos que no devolverá basura, la basura estaría en el sentido de que si un objeto no era atómico y un objeto trató de acceder a él mientras que otro estaba escribiendo en él, podría recuperar el resultado a mitad de escritura, y ¿Solo obtienes una versión parcial e incompleta del cambio provocado por la escritura? ¿Es esto lo que significa "basura" en este sentido, y qué propiedades atómicas ayudan a prevenir?
En programación concurrente:
atomic significa que si un valor de propiedad al que se accede para la operación de escritura en algún subproceso (subproceso # 1) y otro subproceso (subproceso # 2) intenta acceder al valor atómico para la operación de lectura o escritura, entonces el otro subproceso (subproceso # 2) espera hasta que el subproceso # 1 completa su tarea. En otras palabras, la sincronización atómica del acceso de la propiedad se otorga por orden de llegada.
medios no atómicos si un valor de propiedad al que se accede para la operación de escritura en algún subproceso (subproceso # 1) y otro subproceso (subproceso # 2) intenta acceder al valor no atómico para la operación de lectura o escritura, entonces se obtiene otro subproceso (subproceso # 2) el valor se vuelve inmediatamente antiguo
En respuesta a tu tercer párrafo; esencialmente si No se puede leer un número atómico mientras un hilo está escribiendo el número.
Por ejemplo, si un hilo ha escrito los dos primeros bytes de un número atómico de cuatro bytes, y se solicita una lectura de ese número en otro hilo, esa lectura debe esperar hasta que se hayan escrito los cuatro bytes.
A la inversa, si un hilo ha escrito los dos primeros bytes de un número de cuatro bytes no atómico, y se solicita una lectura de ese número en otro hilo en ese momento, leerá los dos primeros bytes de datos nuevos, pero obtendrá datos antiguos de una operación de escritura previa en los otros dos bytes.
Implementación explícita de
@ propiedad (atómica, retener) NSNumber * count
seria asi
- (NSNumber *)count {
NSNumber *count;
@synchronized(self) {
count = [_count retain]; // +1
}
return [count autorelease]; // delayed -1
}
- (void)setCount:(NSNumber *)count {
id oldValue;
@synchronized(self) {
oldValue = _count;
_count = [count retain];
}
[oldValue release];
}
Atomic es el comportamiento predeterminado para una propiedad. Una propiedad atómica agrega un nivel de seguridad de subprocesos al obtener o establecer valores. Es decir, el getter y el setter de la propiedad siempre se completarán completamente, independientemente de lo que hagan los otros hilos. estas propiedades serán un poco más lentas de acceder que un equivalente no atómico.
Y explícitamente lo implementaríamos.
@ propiedad (no atómica, retener) NSNumber * count
Me gusta esto
- (NSNumber *)count {
return _count;
}
- (void)setCount:(NSNumber *)count {
if (count != _count) {
id oldValue = _count;
_count = [count retain];
[_oldValue release];
}
}
Las propiedades no atómicas no son seguras para subprocesos y devolverán sus propiedades directamente. Esto será más rápido que las propiedades atómicas, pero obviamente conlleva cierto riesgo si no se toman precauciones.
setter & getter para estas propiedades no atómicas
La respuesta de Robert Harvey es correcta, pero hay un subcaso de eso para considerar que la gente a menudo falla. Considere este código: http://pastebin.com/S7XyJm6G
Además de evitar que lea valores parcialmente escritos, las propiedades atómicas también le impiden recuperar objetos de los que no controla la vida útil (lo hacen al retener y luego soltar automáticamente el objeto). Esto es importante en el código de un solo subproceso como el ejemplo que vinculé, pero aún más importante en el código de múltiples subprocesos donde otro hilo podría hacer que el objeto se suelte debajo de usted.
Una propiedad atomic
en Objective C garantiza que nunca verá escrituras parciales. Cuando una @property
tiene el atributo atomic
, es imposible escribir solo parcialmente el valor. El setter es así:
- (void)setProp:(NSString *)newValue {
[_prop lock];
_prop = newValue;
[_prop unlock];
}
Entonces, si dos hilos desean escribir el valor @ "test" y @ "otherTest" al mismo tiempo, en un momento dado, la propiedad solo puede ser el valor inicial de la propiedad o @ "test" o @ "otherTest". nonatomic
es más rápido pero el valor es un valor de basura y no hay una Cadena parcial de @ "prueba" / @ "otherTest" (thx @Gavin) o cualquier otro valor de basura.
Pero atomic
solo es seguro para subprocesos con un uso simple. No está garantizado. Appledoc dice lo siguiente:
Considere un objeto
XYZPerson
en el que tanto el nombre como el apellido de una persona se cambian utilizandoXYZPerson
atómicos desde un hilo. Si otro hilo accede a ambos nombres al mismo tiempo, los métodos de obtención atómicos devolverán cadenas completas (sin fallar), pero no hay garantía de que esos valores sean los nombres correctos entre sí. Si se accede al primer nombre antes del cambio, pero se accede al apellido después del cambio, terminará con un par de nombres inconsistentes y no coincidentes.
Nunca tuve un problema usando el atómico en absoluto. Diseñé el código de esa manera, para que no haya problemas con las propiedades atómicas.