¿Qué significa atomic
y qué nonatomic
significa en las declaraciones de propiedad?
@property(nonatomic, retain) UITextField *userName;
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName;
¿Cuál es la diferencia operativa entre estos tres?
ios
objective-c
properties
atomic
nonatomic
Alex Wayne
fuente
fuente
Respuestas:
Los dos últimos son idénticos; "atómico" es el comportamiento predeterminado (
tenga en cuenta que en realidad no es una palabra clave; se especifica solo por la ausencia de-nonatomic
atomic
se agregó como palabra clave en versiones recientes de llvm / clang).Suponiendo que está sintetizando las implementaciones del método, atómico vs. no atómico cambia el código generado. Si está escribiendo su propio setter / getters, atómico / no atómico / retener / asignar / copiar son meramente informativos. (Nota: @synthesize es ahora el comportamiento predeterminado en las versiones recientes de LLVM. Tampoco es necesario declarar las variables de instancia; también se sintetizarán automáticamente y se agregarán
_
previamente a su nombre para evitar el acceso directo accidental).Con "atómico", el setter / getter sintetizado asegurará que todo el setter siempre devuelva valor o que el setter lo devuelva, independientemente de la actividad del setter en cualquier otro hilo. Es decir, si el subproceso A está en el medio del captador mientras el subproceso B llama al establecedor, un valor viable real, un objeto lanzado automáticamente, muy probablemente, se devolverá al llamante en A.
En
nonatomic
, no se hacen tales garantías. Por lo tanto,nonatomic
es considerablemente más rápido que "atómico".Lo que "atomic" no hace es garantizar la seguridad de los hilos. Si el subproceso A está llamando al captador simultáneamente con el subproceso B y C llamando al establecedor con valores diferentes, el subproceso A puede obtener cualquiera de los tres valores devueltos, el anterior a cualquier llamada de los establecedores o cualquiera de los valores pasados a los establecedores 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 programación multiproceso, se logra por otros medios.
Agregando a esto:
atomicity
de una sola propiedad tampoco puede garantizar la seguridad del subproceso cuando varias propiedades dependientes están en juego.Considerar:
En este caso, el hilo A podría renombrar el objeto llamando
setFirstName:
y luego llamandosetLastName:
. Mientras tanto, el hilo B puede llamarfullName
entre las dos llamadas del hilo A y recibirá el nuevo nombre junto con el apellido anterior.Para abordar esto, necesita un modelo transaccional . Es decir, algún otro tipo de sincronización y / o exclusión que le permita a uno excluir el acceso
fullName
mientras se actualizan las propiedades dependientes.fuente
@property NSArray* astronomicalEvents;
lista de datos que quiero mostrar en la interfaz de usuario. Cuando la aplicación inicia el puntero apunta a una matriz vacía, la aplicación extrae datos de la web. Cuando se completa la solicitud web (en un hilo diferente), la aplicación crea una nueva matriz y luego establece atómicamente la propiedad en un nuevo valor de puntero. Es seguro para subprocesos y no tuve que escribir ningún código de bloqueo, a menos que me falte algo. Me parece bastante útil.atomic
evita lecturas de valor medio entre hilos. (Ese fue un error divertido de rastrear.)retain/autorelease
bailar. El hilo B libera el objeto. Hilo A va boom .atomic
asegura que el hilo A tenga una referencia fuerte (un recuento de retención +1) para el valor de retorno.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 una palabra clave "atómica", si no especifica "no atómica", entonces la propiedad es atómica, pero si especifica "atómica" explícitamente se producirá un error.Si no especifica "no atómico", la propiedad es atómica, pero aún puede especificar "atómico" explícitamente en las versiones recientes si lo desea.
Ahora, la variante atómica es un poco más complicada:
Básicamente, la versión atómica tiene que tomar un candado para garantizar la seguridad del hilo, y también está aumentando el recuento de referencia en el objeto (y el recuento de liberación automática para equilibrarlo) de modo que se garantice que el objeto exista para la persona que llama, de lo contrario es una posible condición de carrera si otro subproceso está configurando el valor, lo que hace que el recuento de referencias caiga 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 los elementos de retención, copia, solo lectura, no atómico, etc. En general, los sintetizadores de propiedades simplemente saben cómo hacer "lo correcto" para todas las combinaciones.
fuente
@property (assign) id delegate;
no está sincronizado en nada (iOS SDK GCC 4.2 ARM-Os
), lo que significa que hay una carrera entre[self.delegate delegateMethod:self];
yfoo.delegate = nil; self.foo = nil; [super dealloc];
. Ver stackoverflow.com/questions/917884/…_val
/val
son, pero no, en realidad no. El captador para un atómicacopy
/retain
propiedad necesita para asegurarse de que no devuelve un objeto cuya refcount se convierte en cero debido al colocador de ser llamado en otro hilo, que esencialmente significa que necesita para leer el Ivar, consérvelo garantizando al mismo tiempo que el colocador no tiene sobrescrito y liberado, y luego liberarlo automáticamente para equilibrar la retención. Eso significa esencialmente que tanto el getter como el setter tienen que usar un bloqueo (si se reparó el diseño de la memoria, debería ser posible con las instrucciones CAS2; por desgracia,-retain
es una llamada al método).Atómico
No atómico
fuente
La mejor manera de entender la diferencia es usar el siguiente ejemplo.
Supongamos que hay una propiedad de cadena atómica llamada "nombre", y si llama
[self setName:@"A"]
desde el hilo A, llama[self setName:@"B"]
desde el hilo B y llama[self name]
desde el 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 getter, entonces otros hilos esperarán.Esto hace que la propiedad "nombre" de lectura / escritura sea segura, pero si otro subproceso, D, llama
[name release]
simultáneamente, entonces esta operación puede producir un bloqueo porque no hay una llamada de setter / getter involucrada aquí. Lo que significa que un objeto es seguro para lectura / escritura (ATOMIC), pero no para subprocesos, ya que otros subprocesos pueden enviar simultáneamente cualquier tipo de mensajes al objeto. El desarrollador debe garantizar la seguridad del hilo para tales objetos.Si la propiedad "nombre" no era atómica, entonces todos los hilos en el ejemplo anterior - A, B, C y D se ejecutarán simultáneamente produciendo cualquier resultado impredecible. En caso de atómica, cualquiera de A, B o C se ejecutará primero, pero D aún puede ejecutarse en paralelo.
fuente
La sintaxis y la semántica ya están bien definidas por otras excelentes respuestas a esta pregunta. Como la ejecución y el rendimiento no están bien detallados, agregaré mi respuesta.
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 un 100% de seguridad de roscas es un caso de esquina. Para programas multiproceso verdaderamente correctos, la intervención del programador es casi un requisito. Mientras tanto, las características de rendimiento y ejecución aún no se han detallado en profundidad. Habiendo escrito algunos programas muy multiproceso a lo largo de los años, había estado declarando mis propiedades
nonatomic
todo el tiempo porque atomic no era sensato para ningún propósito. Durante la discusión de los detalles de las propiedades atómicas y no atómicas de esta pregunta , hice algunos perfiles y encontré algunos resultados curiosos.Ejecución
Okay. Lo primero que me gustaría aclarar es que la implementación de bloqueo está definida y resumida en 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)
; utiliza bloqueos 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 se 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 mediante el acceso a propiedades atómicas en casos no disputados (por ejemplo, de un solo 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 de
nonatomic
. Mientras que el caso impugnado con 7 subprocesos 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 al margen interesante: los accesores definidos por el usuario de la estructura de tres bytes fueron 52 veces más rápidos que los accesos atómicos sintetizados; o 84% de la velocidad de los accesos no atómicos sintetizados.
Los objetos en casos disputados también pueden exceder 50 veces.
Debido a la cantidad 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. Obtener los costos reales de los perfiles puede llevar mucho tiempo y, debido a las abstracciones, ser bastante inexactos. Además, ARC vs MRC puede hacer una gran diferencia.
Entonces, retrocedamos, sin centrarnos en la implementación de accesos a la propiedad, incluiremos los sospechosos habituales
objc_msgSend
, y examinaremos algunos resultados de alto nivel del mundo real para muchas llamadas a unNSString
captador en casos no controvertidos (valores en segundos):Como probablemente haya adivinado, la actividad de conteo de referencia / ciclismo es un contribuyente significativo con los atómicos y bajo ARC. También vería mayores diferencias en los casos disputados.
Aunque presto mucha atención al rendimiento, sigo diciendo ¡ Semántica primero! . Mientras tanto, el rendimiento es de 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. Esperemos que esto le ahorre algunas horas de comparación y lo ayude a tomar una decisión mejor informada al diseñar sus programas.
fuente
NSString
que no es inmortal:-ARC atomic (BASELINE): 100% -ARC nonatomic, synthesised: 94% -ARC nonatomic, user defined: 86% -MRC nonatomic, user defined: 5% -MRC nonatomic, synthesised: 19% -MRC atomic: 102%
los resultados son un poco diferentes hoy en día. No estaba haciendo ninguna@synchronized
comparación.@synchronized
es semánticamente diferente, y no lo considero una buena herramienta si tiene programas concurrentes no triviales. si necesitas velocidad, evita@synchronized
.Atómico = seguridad del hilo
No atómico = Sin seguridad de hilo
Hilo de seguridad:
Las variables de instancia son seguras para subprocesos si se comportan correctamente cuando se accede desde múltiples subprocesos, independientemente de la programación o intercalación de la ejecución de esos 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 cambiado está disponible para todos los hilos, y solo un hilo puede cambiar el valor a la vez.
Donde utilizar
atomic
:si se va a acceder a la variable de instancia en un entorno multiproceso.
Implicación de
atomic
:No tan rápido como
nonatomic
porquenonatomic
no requiere ningún trabajo de vigilancia en el tiempo de ejecución.Donde utilizar
nonatomic
:Si la variable de instancia no va a ser cambiada por múltiples hilos, puede usarla. Mejora el rendimiento.
fuente
Encontré una explicación bastante bien puesta de las propiedades atómicas y no atómicas aquí . Aquí hay un texto relevante del mismo:
Debido a que las
atomic
variables no pueden ser interrumpidas, se garantiza que el valor contenido en ellas en cualquier punto (bloqueo de hilo) no se corrompe , aunque garantizar que este bloqueo de hilo haga que el acceso a ellas sea más lento.non-atomic
Las variables, por otro lado, no ofrecen tal garantía, pero ofrecen el lujo de un acceso más rápido. Para resumir, vayanon-atomic
cuando sepa que sus variables no serán accedidas por múltiples hilos simultáneamente y acelerará las cosas.fuente
Después de leer tantos artículos, publicaciones de Stack Overflow y hacer aplicaciones de demostración para verificar los atributos de las propiedades variables, decidí juntar toda la información de los atributos:
atomic
// Defectononatomic
strong = retain
// Defectoweak = unsafe_unretained
retain
assign
// Defectounsafe_unretained
copy
readonly
readwrite
// DefectoEn el artículo Atributos o modificadores de propiedades variables en iOS , puede encontrar todos los atributos mencionados anteriormente, y eso definitivamente lo ayudará.
atomic
atomic
significa que solo un hilo accede a la variable (tipo estático).atomic
es seguro para hilos.atomic
es el comportamiento predeterminadoEjemplo:
nonatomic
nonatomic
significa acceso múltiple a la variable (tipo dinámico).nonatomic
no es seguro para subprocesosnonatomic
NO es un comportamiento predeterminado. Necesitamos agregar lanonatomic
palabra clave en el atributo de propiedad.Ejemplo:
fuente
Atómico:
Atomic garantiza que el acceso a la propiedad se realizará de manera atómica. Por ejemplo, siempre devuelve objetos completamente inicializados, cualquier get / set de una propiedad en un hilo debe completarse antes de que otro pueda acceder a él.
Si imagina que la siguiente función ocurre en dos hilos a la vez, puede ver por qué los resultados no serían bonitos.
Pros: el retorno de objetos totalmente inicializados cada vez es la mejor opción en caso de subprocesos múltiples.
Contras: impacto en el 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 subprocesos múltiples.
fuente
La respuesta más fácil primero: no hay diferencia entre sus dos segundos ejemplos. Por defecto, los accesores de propiedad son atómicos.
Los accesores atómicos en un entorno sin recolección de basura (es decir, cuando se usa retención / liberación / liberación automática) usarán un bloqueo para garantizar que otro hilo no interfiera con la configuración / obtención correcta del valor.
Consulte la sección " Rendimiento y subprocesos " 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.
fuente
Atómico significa que solo un hilo accede a la variable (tipo estático). Atomic es seguro para subprocesos, pero es lento.
No atómico significa que múltiples hilos acceden a la variable (tipo dinámico). Nonatomic no es seguro para subprocesos, pero es rápido.
fuente
Atomic es seguro para subprocesos , es lento y asegura (no está garantizado) que solo se proporciona el valor bloqueado sin importar cuántos subprocesos intenten acceder en la misma zona. Cuando se usa atomic, un fragmento de código escrito dentro de esta función se convierte en parte de la sección crítica, a la que solo se puede ejecutar un subproceso a la vez.
Solo asegura la seguridad del hilo; No garantiza eso. Lo que quiero decir es que contratas a un conductor experto para tu auto, aún así no garantiza que el auto no tenga 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 hace que getter y setter de la propiedad sean seguros. por ejemplo si has escrito:
es seguro para hilos.
NO es seguro para hilos.
fuente
No existe esa palabra clave "atómica"
Podemos usar lo anterior como
Consulte la pregunta sobre desbordamiento de pila. Tengo problemas si uso @property (atomic, retener) NSString * myString .
fuente
Ver más aquí: https://realm.io/news/tmi-objective-c-property-attributes/
fuente
El valor predeterminado es
atomic
, esto significa que le cuesta rendimiento cada vez que usa la propiedad, pero es seguro para subprocesos. Lo que hace Objective-C es establecer un bloqueo, 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 _ interno:
Entonces estos dos últimos son iguales:
Por otro lado, no
nonatomic
agrega nada a su código. Por lo tanto, solo es seguro para subprocesos si codifica usted mismo el mecanismo de seguridad.Las palabras clave no tienen que escribirse como primer atributo de propiedad.
No olvide que esto no significa que la propiedad en su conjunto sea segura para subprocesos. Solo la llamada al método del setter / getter es. Pero si usa un setter y luego un getter al mismo tiempo con 2 hilos diferentes, ¡podría romperse también!
fuente
Antes de comenzar: debe saber que cada objeto en la memoria debe ser desasignado de la memoria para que ocurra un nuevo escritor. No puedes simplemente escribir encima de algo como lo haces en papel. Usted debe borrar primero (dealloc) y luego se puede escribir en él. Si en el momento en que se borra (o se hace a medias) y aún no se ha escrito nada (o se ha escrito a medias) e intenta leerlo, ¡podría ser muy problemático! La ayuda atómica y no atómica lo ayuda a tratar este problema de diferentes maneras.
Primero lea esta pregunta y luego lea la respuesta de Bbum . Además, luego lea mi resumen.
atomic
SIEMPRE garantizará¡¿Qué?! Son multihilo y seguridad de hilo diferentes ?
Si. Multiproceso significa: varios subprocesos pueden leer un dato compartido al mismo tiempo y no nos bloquearemos, sin embargo, no garantiza que no esté leyendo desde un valor no publicado automáticamente. Con la seguridad de subprocesos, se garantiza que lo que lee no se libera automáticamente. La razón por la que no hacemos que todo sea atómico por defecto es que hay un costo de rendimiento y para la mayoría de las cosas realmente no se necesita seguridad en los hilos. Algunas partes de nuestro código lo necesitan y para esas pocas partes, tenemos que escribir nuestro código de manera segura para subprocesos utilizando bloqueos, mutex o sincronización.
nonatomic
En general son diferentes en 2 aspectos:
Falla o no por tener o no tener un grupo de liberación automática.
Permitir que se lea justo en el medio de un "valor de escritura o valor vacío aún no terminado" o no permitir y solo permitir leer cuando el valor está completamente escrito.
fuente
Si está utilizando su propiedad en código multiproceso, entonces podrá ver la diferencia entre los atributos atómicos y no atómicos. Nonatomic es más rápido que atomic y atomic es seguro para subprocesos, no no atómico.
Vijayendra Tripathi ya ha dado un ejemplo para un entorno multiproceso.
fuente
Cómo declarar:
Como atómico es el predeterminado, entonces
Y en el archivo de implementación
Supongamos que una tarea relacionada con tres propiedades son
Todas las propiedades funcionan en paralelo (como asincrónicamente).
Si llamas "nombre" desde el hilo A ,
Y
Al mismo tiempo si llamas
del hilo B ,
Ahora si la propiedad * name no es atómica, entonces
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 * name es atómica
Es por eso que atomic se llama thread Safe y por eso se llama read-write safe
Tal operación de situación se realizará en serie. Y lento en rendimiento
- No atómico significa acceso múltiple a la variable (tipo dinámico).
- No atómico es un hilo inseguro.
- pero es rápido en rendimiento
-Nonatomic NO es un comportamiento predeterminado, debemos agregar una palabra clave no atómica en el atributo de propiedad.
Para In Swift Confirmando que las propiedades Swift son no atómicas en el sentido ObjC. Una razón es para pensar 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
fuente
atomic
es seguro para subprocesos! Es más resistente a los problemas de hilo, pero no es seguro para hilos. Simplemente asegura que obtendrá un valor completo, también conocido como un valor "correcto" (nivel binario), pero de ninguna manera se asegurará de que sea el valor actual y "correcto" para la lógica de su negocio (podría ser un valor pasado y inválido por su lógica).Atomicidad atómica (predeterminado)
no atómico
cortesía https://academy.realm.io/posts/tmi-objective-c-property-attributes/
Los atributos de propiedad de atomicidad (atómica y no atómica) no se reflejan en la declaración de propiedad de Swift correspondiente, pero las garantías de atomicidad de la implementación de Objective-C aún se mantienen cuando se accede a la propiedad importada desde Swift.
Entonces, si define una propiedad atómica en Objective-C, permanecerá atómica cuando Swift la use.
cortesía https://medium.com/@YogevSitton/atomic-vs-non-atomic-properties-crash-course-d11c23f4366c
fuente
La propiedad atómica asegura retener un valor completamente inicializado independientemente de cuántos hilos estén haciendo getter & setter en él.
La propiedad no atómica especifica que los accesos sintetizados simplemente establecen o devuelven un valor directamente, sin garantías sobre lo que sucede si se accede a ese mismo valor simultáneamente desde diferentes hilos.
fuente
Atómico significa que solo un subproceso puede acceder a la variable a la vez (tipo estático). Atomic es seguro para subprocesos, pero es lento.
No atómico significa que varios subprocesos pueden acceder a la variable al mismo tiempo (tipo dinámico). No atómico no es seguro para subprocesos, pero es rápido.
fuente
Si está utilizando atomic, significa que el hilo será seguro y de solo lectura. Si está utilizando no atómico, significa que los múltiples hilos acceden a la variable y no es seguro, pero se ejecuta rápidamente, se realizan operaciones de lectura y escritura; Este es un tipo dinámico.
fuente
La verdad es que usan el bloqueo de giro para implementar la propiedad atómica. El código de la siguiente manera:
fuente
Para simplificar toda la confusión, comprendamos el bloqueo de mutex.
El bloqueo Mutex, según el nombre, bloquea la mutabilidad del objeto. Entonces, si una clase accede al objeto, ninguna otra clase puede acceder al mismo objeto.
En iOS,
@sychronise
también proporciona el bloqueo de mutex. Ahora sirve en modo FIFO y garantiza que el flujo no se vea afectado por dos clases que comparten la misma instancia. Sin embargo, si la tarea está en el subproceso principal, evite acceder al objeto utilizando propiedades atómicas, ya que puede contener su interfaz de usuario y degradar el rendimiento.fuente
Atómico: garantice la seguridad del hilo bloqueándolo con NSLOCK.
No atómico: no garantiza la seguridad del hilo ya que no hay un mecanismo de bloqueo del hilo.
fuente
Propiedades atómicas : cuando una variable asignada con propiedad atómica significa que solo tiene acceso a un subproceso y será seguro para los subprocesos y tendrá una buena perspectiva de rendimiento, tendrá un comportamiento predeterminado.
Propiedades no atómicas : cuando una variable asignada con propiedad atómica significa que tiene acceso a múltiples subprocesos y no será segura para subprocesos y será lenta en la perspectiva de rendimiento, tendrá un comportamiento predeterminado y cuando dos subprocesos diferentes desean acceder a la variable al mismo tiempo dará resultados inesperados
fuente