¿Cuál es la diferencia entre los atributos atómicos y no atómicos?

¿Qué significan atomic y no atomic en las declaraciones de propiedades?

 @property(nonatomic, retain) UITextField *userName; @property(atomic, retain) UITextField *userName; @property(retain) UITextField *userName; 

¿Cuál es la diferencia operativa entre estos tres?

Los dos últimos son idénticos; “atómico” es el comportamiento predeterminado ( tenga en cuenta que no es en realidad una palabra clave, sino que se especifica solo por la ausencia de nonatomic atomic se agregó atomic como palabra clave en las versiones recientes de llvm / clang).

Suponiendo que estás sintetizando las implementaciones del método, los cambios atómicos y no atómicos cambian el código. Si está escribiendo su propio setter / getters, atomic / nonatomic / retain / assign / copy son meramente asesores. (Nota: @synthesize es ahora el comportamiento predeterminado en las versiones recientes de LLVM. Tampoco es necesario declarar variables de instancia, sino que también se sintetizarán automáticamente y tendrán un _ de su nombre para evitar el acceso directo accidental).

Con “atómico”, el setter / getter sintetizado asegurará que siempre se devuelva un valor completo desde el getter o el setter, independientemente de la actividad del setter en cualquier otro thread. Es decir, si el hilo A está en el medio del captador mientras el hilo B llama al colocador, un valor viable real, es decir, un objeto liberado automáticamente, se devolverá a la persona que llama en A.

En nonatomic , no se hacen tales garantías. Por lo tanto, no nonatomic es considerablemente más rápido que “atómico”.

Lo que “atómico” no hace es dar garantías sobre la seguridad del hilo. Si el subproceso A llama al captador de forma simultánea con el subproceso B y C llamando al instalador con valores diferentes, el subproceso A puede obtener cualquiera de los tres valores devueltos, el anterior a que se invoque a cualquier ajustador o se pase cualquiera de los valores a los definidores en B y C. Del mismo modo, el objeto puede terminar con el valor de B o C, no hay forma de saberlo.

Garantizar la integridad de los datos, uno de los principales desafíos de la progtwigción multiproceso, se logra por otros medios.

Agregando a esto:

atomicity de una sola propiedad tampoco puede garantizar la seguridad de la secuencia cuando están en juego múltiples propiedades dependientes.

Considerar:

  @property(atomic, copy) NSString *firstName; @property(atomic, copy) NSString *lastName; @property(readonly, atomic, copy) NSString *fullName; 

En este caso, el subproceso A podría renombrar el objeto al llamar a setFirstName: y luego llamar a setLastName: Mientras tanto, el hilo B puede llamar a fullName entre las dos llamadas del hilo A y recibirá el nuevo nombre junto con el anterior.

Para abordar esto, necesita un modelo transaccional . Es decir, otro tipo de sincronización y / o exclusión que permite excluir el acceso a fullName mientras se actualizan las propiedades dependientes.

Esto se explica en la documentación de Apple, pero a continuación hay algunos ejemplos de lo que realmente está sucediendo. Tenga en cuenta que no hay palabra clave “atómica”, si no especifica “no atómica”, la propiedad es atómica, pero especificar “atómico” explícitamente dará como resultado un error.

 //@property(nonatomic, retain) UITextField *userName; //Generates roughly - (UITextField *) userName { return userName; } - (void) setUserName:(UITextField *)userName_ { [userName_ retain]; [userName release]; userName = userName_; } 

Ahora, la variante atómica es un poco más complicada:

 //@property(retain) UITextField *userName; //Generates roughly - (UITextField *) userName { UITextField *retval = nil; @synchronized(self) { retval = [[userName retain] autorelease]; } return retval; } - (void) setUserName:(UITextField *)userName_ { @synchronized(self) { [userName_ retain]; [userName release]; userName = userName_; } } 

Básicamente, la versión atómica tiene que cerrarse para garantizar la seguridad del hilo, y también está superando el recuento de ref en el objeto (y el recuento de liberación automática para equilibrarlo) de modo que el objeto está garantizado para la persona que llama, de lo contrario habrá es una condición de carrera potencial si otro hilo está configurando el valor, lo que hace que el recuento de ref se reduzca a 0.

En realidad, hay una gran cantidad de variantes diferentes de cómo funcionan estas cosas, dependiendo de si las propiedades son valores u objetos escalares, y cómo interactúan retención, copia, solo lectura, no atómica, etc. En general, los sintetizadores de propiedades solo saben cómo hacer lo “correcto” para todas las combinaciones.

Atómico

  • es el comportamiento predeterminado
  • asegurará que el proceso actual sea completado por la CPU, antes de que otro proceso acceda a la variable
  • no es rápido, ya que garantiza que el proceso se complete por completo

No atómico

  • NO es el comportamiento predeterminado
  • más rápido (para código sintetizado, es decir, para variables creadas usando @property y @synthesize)
  • no seguro para subprocesos
  • puede provocar un comportamiento inesperado, cuando dos procesos diferentes acceden a la misma variable al mismo tiempo

La mejor forma de entender la diferencia es usando el siguiente ejemplo.

Supongamos que hay una propiedad de cadena atómica llamada “nombre”, y si llama [self setName:@"A"] desde el subproceso A, llame [self setName:@"B"] desde el subproceso B y llame a [self name] desde hilo C, entonces todas las operaciones en diferentes hilos se realizarán en serie, lo que significa que si un hilo está ejecutando un setter o un getter, entonces otros hilos esperarán.

Esto hace que la propiedad “nombre” de lectura / escritura sea segura, pero si otro hilo, D, llama a [name release] simultáneamente, entonces esta operación puede producir un locking porque no hay una llamada de establecimiento / captura involucrada aquí. Lo que significa que un objeto es de lectura / escritura segura (ATOMIC), pero no es seguro para subprocesos, ya que otros subprocesos pueden enviar simultáneamente cualquier tipo de mensajes al objeto. El desarrollador debe garantizar la seguridad de subprocesos para dichos objetos.

Si la propiedad “nombre” no fuera atómica, todos los hilos en el ejemplo anterior – A, B, C y D se ejecutarán simultáneamente produciendo cualquier resultado impredecible. En el caso de atómica, cualquiera de A, B o C se ejecutará primero, pero D aún puede ejecutar en paralelo.

La syntax y la semántica ya están bien definidas por otras excelentes respuestas a esta pregunta. Debido a que la ejecución y el rendimiento no se detallan bien, agregaré mi respuesta.

¿Cuál es la diferencia funcional entre estos 3?

Siempre había considerado atómico como un defecto bastante curioso. En el nivel de abstracción en el que trabajamos, el uso de propiedades atómicas para una clase como vehículo para lograr el 100% de seguridad de hilo es un caso de esquina. Para progtwigs verdaderamente correctos de multiproceso, la intervención del progtwigdor es casi seguro un requisito. Mientras tanto, las características de rendimiento y la ejecución aún no se han detallado en profundidad. Después de haber escrito algunos progtwigs muy multiproceso a través de los años, había estado declarando mis propiedades como no nonatomic todo el tiempo porque atómico no era sensato para ningún propósito. Durante la discusión de los detalles de las propiedades atómicas y no atómicas, esta pregunta , hice algunos perfiles y encontré algunos resultados curiosos.

Ejecución

De acuerdo. Lo primero que me gustaría aclarar es que la implementación de locking está definida y definida por la implementación. Louis usa @synchronized(self) en su ejemplo. He visto esto como una fuente común de confusión. La implementación en realidad no usa @synchronized(self) ; usa lockings de giro a nivel de objeto. La ilustración de Louis es buena para una ilustración de alto nivel que utiliza construcciones con las que todos estamos familiarizados, pero es importante saber que no usa @synchronized(self) .

Otra diferencia es que las propiedades atómicas retendrán / liberarán el ciclo de sus objetos dentro del captador.

Actuación

Aquí está la parte interesante: el rendimiento que usa accesos de propiedad atómica en casos no impugnados (por ejemplo, un único subproceso) puede ser realmente muy rápido en algunos casos. En casos menos que ideales, el uso de accesos atómicos puede costar más de 20 veces la sobrecarga no nonatomic . Mientras que el caso impugnado con 7 hilos fue 44 veces más lento para la estructura de tres bytes ( Core i7 Quad Core de 2.2 GHz, x86_64). La estructura de tres bytes es un ejemplo de una propiedad muy lenta.

Nota informativa interesante: los accesadores definidos por el usuario de la estructura de tres bytes eran 52 veces más rápidos que los accesadores atómicos sintetizados; o 84% de la velocidad de los accesadores no atómicos sintetizados.

Los objetos en casos impugnados también pueden exceder 50 veces.

Debido al número de optimizaciones y variaciones en las implementaciones, es bastante difícil medir los impactos del mundo real en estos contextos. A menudo puede escuchar algo como “Confía en él, a menos que hagas un perfil y descubras que es un problema”. Debido al nivel de abstracción, en realidad es bastante difícil medir el impacto real. Recolectar los costos reales de los perfiles puede consumir mucho tiempo, y debido a las abstracciones, es bastante impreciso. Además, ARC vs MRC puede hacer una gran diferencia.

Así que retrocedamos, sin centrarnos en la implementación de accesos a propiedades, incluiremos los sospechosos habituales como objc_msgSend y examinaremos algunos resultados de alto nivel del mundo real para muchas llamadas a un captador de NSString en casos no impugnados (valores en segundos):

  • MRC | no atómico | getters implementados manualmente: 2
  • MRC | no atómico | Gancho sintetizado: 7
  • MRC | atómico | captador sintetizado: 47
  • ARC | no atómico | captador sintetizado: 38 (nota: ARC está agregando recuento de ref aquí en bicicleta)
  • ARC | atómico | captador sintetizado: 47

Como probablemente haya adivinado, la actividad / ciclo de recuento de referencia es un contribuyente significativo con átomos y bajo ARC. También verías mayores diferencias en los casos impugnados.

Aunque prest mucha atención al rendimiento, ¡todavía digo Semántica primero! . Mientras tanto, el rendimiento es una baja prioridad para muchos proyectos. Sin embargo, conocer los detalles de ejecución y los costos de las tecnologías que usa ciertamente no hace daño. Debe usar la tecnología adecuada para sus necesidades, propósitos y habilidades. Con suerte, esto le ahorrará unas horas de comparaciones y le ayudará a tomar una decisión mejor informada al diseñar sus progtwigs.

Atomic = seguridad de hilo

No atómico = Sin seguridad de hilo

Seguridad del hilo:

Las variables de instancia son seguras para subprocesos si se comportan correctamente cuando se accede desde varios subprocesos, independientemente de la progtwigción o el entrelazado de la ejecución de dichos subprocesos por el entorno de tiempo de ejecución, y sin sincronización adicional u otra coordinación por parte del código de llamada.

En nuestro contexto:

Si un hilo cambia el valor de la instancia, el valor modificado está disponible para todos los hilos, y solo un hilo puede cambiar el valor a la vez.

Dónde usar atomic :

si se va a acceder a la variable de instancia en un entorno multiproceso.

Implicación de atomic :

No tan rápido como no nonatomic porque no nonatomic no requiere ningún trabajo de vigilancia desde el tiempo de ejecución.

Dónde usar no nonatomic :

Si la variable de instancia no va a cambiarse por varios hilos, puede usarla. Mejora el rendimiento.

Encontré aquí una explicación bastante buena de las propiedades atómicas y no atómicas. Aquí hay un texto relevante de la misma:

‘atómico’ significa que no se puede descomponer. En términos de OS / progtwigción, una llamada a función atómica es una que no se puede interrumpir: toda la función debe ejecutarse y no intercambiarse fuera de la CPU por el cambio de contexto habitual del sistema operativo hasta que esté completa. En caso de que no lo supiera: dado que la CPU solo puede hacer una cosa a la vez, el sistema operativo gira el acceso a la CPU a todos los procesos en ejecución en pequeños intervalos de tiempo, para dar la ilusión de la multitarea. El progtwigdor de la CPU puede (y lo hace) interrumpir un proceso en cualquier punto de su ejecución, incluso en una llamada de función intermedia. Por lo tanto, para acciones como actualizar variables de contador compartidas donde dos procesos podrían intentar actualizar la variable al mismo tiempo, deben ejecutarse ‘atómicamente’, es decir, cada acción de actualización debe finalizar en su totalidad antes de que cualquier otro proceso pueda intercambiarse en el UPC.

Así que supongo que atómico en este caso significa que los métodos de lectura de atributos no se pueden interrumpir, lo que significa que la (s) variable (s) que lee el método no pueden cambiar su valor a la mitad porque se obtiene algún otro subproceso / llamada / función. intercambiado en la CPU.

Debido a que las variables atomic no se pueden interrumpir, el valor que contienen en cualquier punto es (thread-lock) garantizado que no está dañado , aunque, al asegurar que este locking de thread hace que el acceso a ellos sea más lento. non-atomic variables non-atomic , por otro lado, no ofrecen tal garantía pero ofrecen el lujo de un acceso más rápido. Para resumir, vaya con non-atomic cuando sabe que sus variables no serán accedidas por múltiples hilos simultáneamente y acelerará las cosas.

Después de leer tantos artículos, astackr las publicaciones de Overflow y hacer aplicaciones de demostración para verificar los atributos de propiedad de las variables, decidí juntar toda la información de los atributos:

  1. atomic // Predeterminado
  2. nonatomic
  3. strong = retain // Predeterminado
  4. weak = unsafe_unretained
  5. retain
  6. assign // Predeterminado
  7. unsafe_unretained
  8. copy
  9. readonly
  10. readwrite // Predeterminado

En el artículo Variables de propiedades o modificadores en iOS , puede encontrar todos los atributos mencionados anteriormente, y eso definitivamente lo ayudará.

  1. atomic

    • atomic significa que solo un hilo accede a la variable (tipo estático).
    • atomic es seguro para subprocesos.
    • Pero es lento en rendimiento
    • atomic es el comportamiento predeterminado
    • Los accesadores atómicos en un entorno no recogido de basura (es decir, cuando se usa retener / liberar / autorrelease) utilizarán un locking para garantizar que otro subproceso no interfiera con la configuración / obtención correcta del valor.
    • En realidad no es una palabra clave.

    Ejemplo:

      @property (retain) NSString *name; @synthesize name; 
  2. nonatomic

    • nonatomic significa acceso múltiple a la variable (tipo dynamic).
    • nonatomic es inseguro para hilos.
    • Pero es rápido en rendimiento
    • nonatomic NO es comportamiento predeterminado. Necesitamos agregar la palabra clave no nonatomic en el atributo de propiedad.
    • Puede provocar un comportamiento inesperado, cuando dos procesos (hilos) diferentes acceden a la misma variable al mismo tiempo.

    Ejemplo:

      @property (nonatomic, retain) NSString *name; @synthesize name; 

La respuesta más fácil primero: no hay diferencia entre los dos segundos ejemplos. Por defecto, los accesores de propiedad son atómicos.

Los accesadores atómicos en un entorno no recogido de basura (es decir, cuando se usa retener / liberar / autorrelease) utilizarán un locking para garantizar que otro subproceso no interfiera con la configuración / obtención correcta del valor.

Consulte la sección ” Rendimiento y subprocesamiento ” de la documentación de Objective-C 2.0 de Apple para obtener más información y otras consideraciones al crear aplicaciones de subprocesos múltiples.

Atómico

Garantías atómicas de que el acceso a la propiedad se realizará de forma atómica. Por ejemplo, siempre devuelve un objeto completamente inicializado, cualquier obtención / conjunto de una propiedad en un hilo debe completarse antes de que otro pueda acceder a él.

Si imagina que la siguiente función se produce en dos hilos a la vez, puede ver por qué los resultados no serían bonitos.

 -(void) setName:(NSString*)string { if (name) { [name release]; // what happens if the second thread jumps in now !? // name may be deleted, but our 'name' variable is still set! name = nil; } ... } 

Pros: El retorno de objetos completamente inicializados cada vez lo convierte en la mejor opción en caso de multi-threading.

Contras: golpe de rendimiento, hace que la ejecución sea un poco más lenta

No atómico:

A diferencia de Atomic, no garantiza el retorno de objetos completamente inicializados cada vez.

Pros: ejecución extremadamente rápida.

Contras: Posibilidades de valor de basura en caso de multi-threading.

Atómico significa que solo un hilo accede a la variable (tipo estático). Atomic es seguro para subprocesos, pero es lento.

Nonatomic significa que múltiples hilos acceden a la variable (tipo dynamic). Nonatomic es inseguro, pero es rápido.

Atomic es seguro para subprocesos , es lento y garantiza (no se garantiza) que solo se proporciona el valor bloqueado sin importar cuántos subprocesos intenten acceder en la misma zona. Cuando se usa atómico, una parte del código escrito dentro de esta función se convierte en la parte de la sección crítica, a la que solo se puede ejecutar un hilo a la vez.

Solo asegura la seguridad del hilo; no garantiza eso. Lo que quiero decir es que contratas un conductor experto para tu auto, pero no garantiza que el auto no sufra un accidente. Sin embargo, la probabilidad sigue siendo la más mínima.

Atómico: no se puede descomponer, por lo que se espera el resultado. Con no atómico: cuando otro subproceso accede a la zona de memoria, puede modificarlo, por lo que el resultado es inesperado.

Code Talk:

Atomic make getter y setter del hilo de propiedad seguro. por ejemplo, si has escrito:

 self.myProperty = value; 

es seguro para subprocesos

 [myArray addObject:@"Abc"] 

NO es seguro para subprocesos

No existe tal palabra clave “atómica”

 @property(atomic, retain) UITextField *userName; 

Podemos usar lo anterior como

 @property(retain) UITextField *userName; 

Consulte la pregunta sobre el desbordamiento de stack. Tengo problemas si uso @property (atomic, retain) NSString * myString .

El valor predeterminado es atomic , esto significa que le cuesta rendimiento siempre que usa la propiedad, pero es seguro para subprocesos. Lo que hace Objective-C, es establecer un locking, por lo que solo el hilo real puede acceder a la variable, siempre que se ejecute el setter / getter.

Ejemplo con MRC de una propiedad con un ivar _internal:

 [_internal lock]; //lock id result = [[value retain] autorelease]; [_internal unlock]; return result; 

Entonces estos dos últimos son iguales

 @property(atomic, retain) UITextField *userName; @property(retain) UITextField *userName; // defaults to atomic 

Por otro lado, no nonatomic no agrega nada a tu código. Por lo tanto, solo es seguro para hilos si codifica el mecanismo de seguridad usted mismo.

 @property(nonatomic, retain) UITextField *userName; 

Las palabras clave no tienen que escribirse como primer atributo de propiedad.

No olvide, esto no significa que la propiedad en su conjunto es segura para subprocesos. Solo la llamada de método del setter / getter es. ¡Pero si usas un setter y luego un getter al mismo tiempo con 2 hilos diferentes, también podría romperse!

atómico (predeterminado)

Atomic es el valor predeterminado: si no escribe nada, su propiedad es atómica. Se garantiza una propiedad atómica que si intenta leer de ella, obtendrá un valor válido. No ofrece ninguna garantía sobre el valor que podría tener, pero obtendrá buenos datos, no solo la memoria no deseada. Lo que esto le permite hacer es si tiene múltiples hilos o múltiples procesos apuntando a una sola variable, un hilo puede leer y otro hilo puede escribir. Si tocan al mismo tiempo, se garantiza que el hilo del lector obtendrá uno de los dos valores: antes del cambio o después del cambio. Lo que atomic no te ofrece es algún tipo de garantía sobre cuáles de esos valores podrías obtener. Atomic es comúnmente confundido con ser seguro para subprocesos, y eso no es correcto. Debe garantizar la seguridad de su hilo de otras maneras. Sin embargo, atomic te garantiza que si tratas de leer, obtienes algún tipo de valor.

no atómico

Por otro lado, no atómico, como probablemente puedas adivinar, solo significa “no hagas esas cosas atómicas”. Lo que pierdes es la garantía de que siempre recuperas algo. Si intenta leer en medio de una escritura, podría recuperar datos basura. Pero, por otro lado, vas un poco más rápido. Debido a que las propiedades atómicas tienen que hacer algo de magia para garantizar que recuperarás un valor, son un poco más lentas. Si es una propiedad a la que está accediendo mucho, puede desear pasar a no atómico para asegurarse de no incurrir en esa penalización de velocidad.

Ver más aquí: https://realm.io/news/tmi-objective-c-property-attributes/

Si está utilizando su propiedad en código de subprocesos múltiples, entonces podrá ver la diferencia entre atributos atómicos y no atómicos. Nonatomic es más rápido que atomic y atomic es thread-safe, no no atómico.

Vijayendra Tripathi ya dio un ejemplo para un entorno de subprocesos múltiples.

  • -Atomic significa que solo un hilo accede a la variable (tipo estático).
  • -Atomic es seguro para subprocesos.
  • -pero es lento en rendimiento

Cómo declarar:

Como atómico es el predeterminado,

 @property (retain) NSString *name; 

Y en archivo de implementación

 self.name = @"sourov"; 

Supongamos que una tarea relacionada con tres propiedades es

  @property (retain) NSString *name; @property (retain) NSString *A; @property (retain) NSString *B; self.name = @"sourov"; 

Todas las propiedades funcionan de forma paralela (como asincrónicamente).

Si llamas “nombre” del hilo A ,

Y

Al mismo tiempo, si llamas

 [self setName:@"Datta"] 

del hilo B ,

Ahora si la propiedad * name no es atómica, entonces

  • Devolverá el valor “Datta” para A
  • Devolverá el valor “Datta” para B

Es por eso que no atómico se llama hilo inseguro Pero es rápido en rendimiento debido a la ejecución paralela

Ahora si * la propiedad del nombre es atómica

  • Asegurará valor “Sourov” para A
  • Luego devolverá el valor “Datta” para B

Es por eso que atomic se llama thread safe y es por eso que se llama safe-write safe

Tal operación de situación se realizará en serie. Y lento en rendimiento

– Nonatomic significa acceso múltiple a la variable (tipo dynamic).

– Nonatomic es thread inseguro.

– pero es rápido en rendimiento

-Natural no es un comportamiento predeterminado, necesitamos agregar una palabra clave no atómica en el atributo de propiedad.

Para In Swift Confirmar que las propiedades Swift no son atómicas en el sentido ObjC. Una razón es para que piense si la atomicidad por propiedad es suficiente para sus necesidades.

Referencia: https://forums.developer.apple.com/thread/25642

Para obtener más información, visite el sitio web http://rdcworld-iphone.blogspot.in/2012/12/variable-property-attributes-or.html

Antes de hablar sobre los atributos de @property, debe saber cuál es el uso de @property. @property ofrece una forma de definir la información que una clase pretende encapsular. If you declare an object/variable using @property, then that object/variable will be accessible to other classes importing its class. If you declare an object using @property in the header file, then you have to synthesize it using @synthesize in the implementation file.

Ejemplo:

.h class

 @interface ExampleClass : NSObject @property (nonatomic, retain) NSString *name; @end 

.m class

 @implementation ExampleClass @synthesize name; @end 

Now the compiler will synthesize accessor methods for name.

 ExampleClass *newObject=[[ExampleClass alloc]init]; NSString *name1=[newObject name]; // get 'name' [obj setName:@“Tiger”]; 

List of attributes of @property : atomic. nonatomic. retain. copy. readonly. readwrite. assign. strong.

atomic : It is the default behaviour. If an object is declared as atomic then it becomes thread-safe. Thread-safe means, at a time only one thread of a particular instance of that class can have the control over that object.

Ejemplo:

 @property NSString *name; //by default atomic @property (atomic)NSString *name; // explicitly declared atomic 

nonatomic: It is not thread-safe. You can use the nonatomic property attribute to specify that synthesized accessors simply set or return a value directly, with no guarantees about what happens if that same value is accessed simultaneously from different threads. For this reason, it’s faster to access a nonatomic property than an atomic one. @property (nonatomic)NSString *name;

retain: is required when the attribute is a pointer to an object.The setter method will increase retain count of the object, so that it will occupy memory in autorelease pool. @property (retain)NSString *name;

copy: If you use copy, you can’t use retain. Using copy instance of the class will contain its own copy. Even if a mutable string is set and subsequently changed, the instance captures whatever value it has at the time it is set. No setter and getter methods will be synthesized.

 @property (copy) NSString *name; NSMutableString *nameString = [NSMutableString stringWithString:@"Liza"]; xyzObj.name = nameString; [nameString appendString:@"Pizza"]; 

readonly: If you don’t want to allow the property to be changed via setter method, you can declare the property readonly. @property (readonly) NSString *name;

readwrite: is the default behaviour. You don’t need to specify readwrite attribute explicitly.

@property (readwrite) NSString *name;

assign: will generate a setter which assigns the value to the instance variable directly, rather than copying or retaining it. This is best for primitive types like NSInteger and CGFloat, or objects you don’t directly own, such as delegates.

@property (assign) NSInteger year;

strong: is a replacement for retain. @property (nonatomic, strong) AVPlayer *player;

unsafe_unretained: There are a few classes in Cocoa and Cocoa Touch that don’t yet support weak references, which means you can’t declare a weak property or weak local variable to keep track of them. These classes include NSTextView, NSFont and NSColorSpace,etc. If you need to use a weak reference to one of these classes, you must use an unsafe reference. An unsafe reference is similar to a weak reference in that it doesn’t keep its related object alive, but it won’t be set to nil if the destination object is deallocated.

@property (unsafe_unretained) NSObject *unsafeProperty;

Before you begin: You must know that every object in memory needs to be deallocated from memory for a new write to happen. You can’t just simply write on top of something as you do on paper. You must first erase (dealloc) it and then you can write onto it. If at the moment that the erase is done (or half done) and nothing has yet been wrote (or half wrote) and you try to read it could be very problematic! Atomic and nonatomic help you treat this problem in different ways.

First read this question and then read Bbum’s answer . In addition then read my summary.


atomic will ALWAYS guarantee

  • If two different people want to read and write at the same time, your paper won’t just burn! –> Your application will never crash, even in a race condition.
  • If one person is trying to write and has only wrote 4 of the 8 letters to written, then no can read in the middle, the reading can only be done when all 8 letters is written –> No read(get) will happen on ‘a thread that is still writing’, ie if there are 8 bytes to bytes to be written, and only 4 bytes are written——up to that moment, you are not allowed to read from it. But since I said it won’t crash then it would read from the value of an autoreleased object.
  • If before writing you have erased that which was previously written on paper and then someone wants to read you can still read. ¿Cómo? You will be reading from something similar to Mac OS Trash bin ( as Trash bin is not still 100% erased…it’s in a limbo) —> If ThreadA is to read while ThreadB has already dealloced to write, you would could either get value from the final fully written value by ThreadB or get something from autorelease pool.

Retain counts are the way in which memory is managed in Objective-C. When you create an object, it has a retain count of 1. When you send an object a retain message, its retain count is incremented by 1. When you send an object a release message, its retain count is decremented by 1. When you send an object an autorelease message , its retain count is decremented by 1 at some stage in the future. If an objectʼs retain count is reduced to 0, it is deallocated.

  • Atomic doesn’t guarantee thread safety, though its useful for achieving thread safety. Thread Safety is relative to how you write your code/ which thread queue you are reading/writing from. It only guarantees non-crashable multithreading.

Wait what?! Are multithreading and thread safety different?

Sí. Multithreading means: multiple threads can read a shared piece of data at the same time and we will not crash, yet it doesn’t guarantee that you aren’t reading from a non-autoreleased value. With thread safety, it’s guaranteed that what you read is not auto-released. The reason that we don’t make everything atomic by default is, because there is a performance cost and for most things don’t really need thread safety. A few parts of our code need it and for those few parts we need to write our code in a thread safe way using locks, mutex or synchronization.


nonatomic

  • Since there is no such thing like Mac OS Trash Bin, then nobody cares whether or not you always get a value (<-- This could potentially lead to a crash), nor anybody cares if someone tries to read halfway through you writing (although halfway writing in memory is very different from halfway writing on paper, on memory it could give you a crazy stupid value from before, while on paper you only see half of what's been wrote) --> Doesn’t guarantee to not crash, because it doesn’t use autorelease mechanism.
  • Doesn’t guarantee full written values to be read!
  • Is faster than atomic

Overall they are different in 2 aspects:

  • Crashing or not because of having or not having autorelease pool.

  • Allowing to be read right in the middle of a ‘not yet finished write or empty value’ or not allowing and only allowing to read when the value is fully written.

The atomic property ensures to retain a fully initialised value irrespective of how many threads are doing getter & setter on it.

The nonatomic property specifies that synthesized accessors simply set or return a value directly, with no guarantees about what happens if that same value is accessed simultaneously from different threads.

Atomic means only one thread can access the variable at a time (static type). Atomic is thread-safe, but it is slow.

Nonatomic means multiple threads can access the variable at same time (dynamic type). Nonatomic is thread-unsafe, but it is fast.

If you are using atomic, it means the thread will be safe and read-only. If you are using nonatomic, it means the multiple threads access the variable and is thread unsafe, but it is executed fast, done a read and write operations; this is a dynamic type.

Atomic: Ensure thread-safety by locking the thread using NSLOCK.

Non atomic: Doesn’t ensure thread-safety as there is no thread-locking mechanism.

To simplify the entire confusion let us understand mutex lock.Mutex lock as per the name locks the mutability of the object.So if the object is accessed by a class no other class can access the same object.In iOS @sychronise also provide the mutex lock.Now it serve in FIFO mode and ensures the flow is not affected by two classes sharing the same instance.However if the task is on main thread avoid accessing object using atomic properties as it may hold your UI and degrade the performance

The truth is that they use spin lock to implement atomic property. The code as below:

  static inline void reallySetProperty(id self, SEL _cmd, id newValue, ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy) { id oldValue; id *slot = (id*) ((char*)self + offset); if (copy) { newValue = [newValue copyWithZone:NULL]; } else if (mutableCopy) { newValue = [newValue mutableCopyWithZone:NULL]; } else { if (*slot == newValue) return; newValue = objc_retain(newValue); } if (!atomic) { oldValue = *slot; *slot = newValue; } else { spin_lock_t *slotlock = &PropertyLocks[GOODHASH(slot)]; _spin_lock(slotlock); oldValue = *slot; *slot = newValue; _spin_unlock(slotlock); } objc_release(oldValue); } 

Atomic properties :- When a variable assigned with atomic property that means it has only one thread access and it will be thread safe and will be good in performance perspective, will have default behaviour.

Non Atomic Properties :- When a variable assigned with atomic property that means it has multi thread access and it will not be thread safe and will be slow in performance perspective, will have default behaviour and when two different threads want to access variable at same time it will give unexpected results.

    Intereting Posts