Quelle est la différence entre les attributs atomiques et non atomiques?
que signifient atomic
et nonatomic
dans les déclarations de biens?
@property(nonatomic, retain) UITextField *userName;
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName;
Quelle est la différence opérationnelle entre ces trois-là?
26 réponses
les deux derniers sont identiques; "atomic" est le comportement par défaut ( notez qu'il n'est pas réellement un mot-clé; il est spécifié seulement par l'absence de -- nonatomic
atomic
a été ajouté comme mot clé dans les versions récentes de llvm/clang).
en supposant que vous synthétisez les implémentations de la méthode, atomique vs. non-atomique change le code généré. Si vous écrivez votre propre définition/getters, atomique/nonatomic/conserver/affecter/copier sont simplement consultatif. (Note: @synthize est maintenant le comportement par défaut dans les versions récentes de LLVM. Il n'est pas non plus nécessaire de déclarer les variables d'instance; elles seront synthétisées automatiquement, elles aussi, et auront un _
préprogrammé à leur nom pour éviter un accès direct accidentel).
avec "atomic", le setter/getter synthétisé veillera à ce qu'une valeur entière soit toujours retournée à partir du setter ou du setter, indépendamment de activité de setter sur n'importe quel autre fil. C'est-à-dire que si le thread A est au milieu du getter alors que le thread B appelle le setter, une valeur réelle viable -- un objet auto-libéré, très probablement -- sera retournée à L'appelant en A.
Dans nonatomic
, aucune de ces garanties sont apportées. Ainsi, nonatomic
est considérablement plus rapide que"atomique".
Ce "atomique" ne pas à faire est de prendre des garanties sur la sécurité des threads. Si le thread A appelle le getter simultanément avec le thread B et C appelant le setter avec des valeurs différentes, le thread a peut obtenir n'importe laquelle des trois valeurs retournées -- celle avant que n'importe quel setter soit appelé ou l'une des valeurs passées dans les setters en B et C. de même, l'objet peut finir avec la valeur de B ou C, aucune façon de dire.
assurer l'intégrité des données -- l'un des principaux défis de la programmation multi-threads -- est réalisé par d'autres moyens.
ajoutant à cela:
atomicity
d'une seule propriété ne peut pas non plus garantir la sécurité du fil lorsque plusieurs propriétés dépendantes sont en jeu.
prendre en considération:
@property(atomic, copy) NSString *firstName;
@property(atomic, copy) NSString *lastName;
@property(readonly, atomic, copy) NSString *fullName;
dans ce cas, le fil A pourrait renommer l'objet en appelant setFirstName:
puis en appelant setLastName:
. En attendant, thread B peut appeler fullName
entre les deux appels de thread A et recevra le nouveau Premier nom couplé avec l'ancien nom.
pour répondre à cela, vous avez besoin d'un modèle transactionnel . C'est-à-dire: une autre sorte de synchronisation et/ou d'exclusion qui permet d'exclure l'accès à fullName
pendant que les propriétés dépendantes sont mises à jour.
cela est expliqué dans la d'Apple" documentation , mais ci-dessous sont quelques exemples de ce qui se passe réellement. Notez qu'il n'y a pas de mot-clé" atomic", si vous ne spécifiez pas" nonatomic "alors la propriété est atomic, mais spécifier" atomic " explicitement résultera en une erreur.
//@property(nonatomic, retain) UITextField *userName;
//Generates roughly
- (UITextField *) userName {
return userName;
}
- (void) setUserName:(UITextField *)userName_ {
[userName_ retain];
[userName release];
userName = userName_;
}
maintenant, la variante atomique est un peu plus compliquée:
//@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_;
}
}
en gros, la version atomique doit prendre une serrure pour pour garantir la sécurité du thread, et est également en bumping le compte ref Sur l'objet (et le compte autorelease pour l'équilibrer) de sorte que l'objet est garanti d'exister pour l'appelant, sinon il ya une condition de course potentielle si un autre thread est de définir la valeur, ce qui provoque le compte ref de tomber à 0.
il existe en fait un grand nombre de variantes différentes de la façon dont ces choses fonctionnent selon que les propriétés sont des valeurs scalaires ou des objets, et comment conserver, copier, readonly, nonatomic, etc interagir. En général, les synthétiseurs de propriété savent simplement faire la "bonne chose" pour toutes les combinaisons.
atomique
- est le comportement par défaut
- assurera que le processus actuel est complété par le CPU, avant qu'un autre processus accède à la variable
- n'est pas rapide, car il assure que le processus est entièrement terminé
Non Atomique
- n'est pas le comportement par défaut
- plus rapide (pour le code synthétisé, c'est-à-dire pour les variables créé à l'aide de @bien et @synthétiser)
- non thread-safe
- peut entraîner un comportement inattendu, lorsque deux processus différents accèdent à la même variable au même moment
la meilleure façon de comprendre la différence est d'utiliser l'exemple suivant.
supposons qu'il y ait une propriété de chaîne atomique appelée "name", et si vous appelez [self setName:@"A"]
à partir du thread A, appelez [self setName:@"B"]
à partir du thread B, et appelez [self name]
à partir du thread C, alors toutes les opérations sur les différents threads seront effectuées en série, ce qui signifie que si un thread exécute un setter ou un getter, alors les autres threads attendront.
Cela fait propriété "name" lit / écrit en toute sécurité, mais si un autre thread, D, Appelle [name release]
simultanément, alors cette opération pourrait produire un crash parce qu'il n'y a pas d'appel setter/getter impliqué ici. Ce qui signifie qu'un objet est sûr en lecture/écriture (atomique), mais pas sûr pour les threads car un autre threads peut simultanément envoyer n'importe quel type de messages à l'objet. Le développeur doit assurer la sécurité des threads pour ces objets.
si la propriété "name" était non atomique, alors tous les fils dans l'exemple ci-dessus - A,B, C et D s'exécutera simultanément produisant n'importe quel résultat imprévisible. Dans le cas de l'atome, l'un de A, B ou C s'exécute en premier, mais D peut encore s'exécuter en parallèle.
la syntaxe et La sémantique sont déjà bien définis par d'autres excellentes réponses à cette question. Parce que exécution et performance ne sont pas bien détaillés, je vais ajouter ma réponse.
Quelle est la différence fonctionnelle entre ces 3?
j'ai toujours considéré atomic comme un défaut assez curieux. Au niveau de l'abstraction, nous travaillons en utilisant les propriétés atomiques pour une classe comme un véhicule pour atteindre 100% filetage-sécurité est un boîtier d'angle. Pour des programmes vraiment corrects multithreaded, l'intervention du programmeur est presque certainement une exigence. Entre-temps, les caractéristiques de rendement et l'exécution n'ont pas encore été détaillées en profondeur. Ayant écrit quelques programmes fortement multithreaded au cours des années, j'avais déclaré mes propriétés comme nonatomic
tout le temps parce qu'atomic n'était pas raisonnable pour aucun but. Au cours de la discussion des détails de l'atomique et nonatomic propriétés cette question , j'ai fait quelques profilage rencontré certains de curieux résultats.
exécution
Ok. La première chose que je voudrais clarifier est que l'implémentation de verrouillage est définie et abstraite. Louis utilise @synchronized(self)
dans son exemple, j'ai vu cela comme une source de confusion. La mise en œuvre ne réellement utiliser @synchronized(self)
; il utilise le niveau d'objet Spin locks . L'illustration de Louis est bonne pour une illustration de haut niveau utilisant des constructions que nous connaissons tous, mais il est important de savoir qu'elle n'utilise pas @synchronized(self)
.
une autre différence est que les propriétés atomiques retiendront/libéreront le cycle de vos objets dans le getter.
Performance
Voici la partie intéressante: La Performance en utilisant les accès de propriété atomique dans les cas non contestés (par exemple monofiltre) peut être vraiment très rapide dans certains cas. Dans des cas moins qu'idéaux, l'utilisation des accès atomiques peut coûter plus de 20 fois la hauteur de nonatomic
. Alors que le cas contesté utilisant 7 threads était 44 fois plus lent pour la structure à trois octets (2,2 GHz Core i7 Quad Core, x86_64). La structure à trois octets est un exemple de structure très lente. propriété.
note intéressante: les accesseurs définis par L'utilisateur de la structure à trois octets étaient 52 fois plus rapides que les accesseurs atomiques synthétisés; ou 84% de la vitesse des accesseurs Non atomiques synthétisés.
les objets dans les cas contestés peuvent également dépasser 50 fois.
en raison du nombre d'optimisations et de variations dans les implémentations, il est assez difficile de mesurer les impacts réels dans ces contextes. Vous pourriez souvent entendre quelque chose comme"faites-lui confiance, à moins que vous le profilez et trouvez qu'il est un problème". En raison du niveau d'abstraction, il est en fait assez difficile de mesurer l'impact réel. Glaner les coûts réels à partir des profils peut prendre beaucoup de temps, et en raison d'abstractions, tout à fait inexacte. De plus, ARC contre MRC peut faire une grande différence.
alors prenons du recul, pas en se concentrant sur la mise en œuvre des accès à la propriété, nous allons inclure les suspects habituels comme objc_msgSend
, et examiner quelques résultats de haut niveau du monde réel pour de nombreux appels à un NSString
getter dans non contestés cas (valeurs en secondes):
- MRC / nonatomic | handly implemented getters: 2
- MRC | nonatomic | synthétisés de lecture: 7
- MRC | atomic | synthétisés de lecture: 47
- ARC | nonatomic | synthétisés de lecture: 38 (note: l'ARC de l'ajout de comptage ref vélo ici)
- ARC | atomic | synthétisés de lecture: 47
comme vous l'avez probablement deviné, l'activité de comptage de référence/le cyclage est un contributeur significatif avec les atomics et sous L'ARC. Vous verriez aussi des différences plus grandes dans les cas contestés.
bien que je sois attentif aux performances, je dis toujours sémantique D'abord! . Entre-temps, la performance est une faible priorité pour de nombreux projets. Cependant, sachant que les détails d'exécution et les coûts des technologies que vous utilisez ne nuisent certainement pas. Vous devez utiliser la technologie adaptée à vos besoins, objectifs et capacités. Nous espérons que cela vous permettra d'économiser quelques heures de comparaisons et vous aidera à prendre une décision plus éclairée lors de la conception de vos programmes.
Atomique = thread de sécurité
Non-atomique = Pas de filetage de sécurité
sécurité des fils:
les variables D'Instance sont sans thread si elles se comportent correctement lorsqu'elles sont accessibles à partir de plusieurs threads, indépendamment de la programmation ou de l'interconnexion de l'exécution de ces threads par l'environnement runtime, et sans synchronisation supplémentaire ou autre coordination de la part le code appelant.
dans notre contexte:
Si un thread modifie la valeur de l'exemple, la valeur modifiée est disponible pour tous les threads, et un seul thread peut modifier la valeur à la fois.
où utiliser atomic
:
si la variable d'instance est accessible dans un environnement multithread.
Implication de atomic
:
Pas comme vite que nonatomic
parce que nonatomic
ne nécessite pas de surveillance des travaux d'exécution .
où utiliser nonatomic
:
si la variable d'instance ne va pas être changée par plusieurs threads, vous pouvez l'utiliser. Il améliore les performances.
j'ai trouvé une explication assez bien formulée des propriétés atomiques et non atomiques ici . Voici quelques textes pertinents de la même:
'atomique' signifie qu'il ne peut pas être divisé. En termes D'OS/programmation un appel de fonction atomique est un appel qui ne peut pas être interrompu - la fonction entière doit être exécutée, et ne pas être échangée hors du CPU par la commutation de contexte habituelle de L'OS jusqu'à ce qu'il soit complet. Juste au cas où vous ne le saviez pas: depuis le CPU ne peut faire qu'une chose à la fois, L'OS fait tourner l'accès au CPU à tous les processus en cours d'exécution en petits tranches de temps, pour donner l'illusion 1519100920 "de multitâche. Le programmeur CPU peut (et fait) interrompre un processus à tout moment de son exécution - même dans l'appel de mi-fonction. Ainsi, pour les actions comme la mise à jour des variables de compteur partagées où deux processus pourraient essayer de mettre à jour la variable en même temps, elles doivent être exécutées "atomiquement", c'est-à-dire que chaque action de mise à jour doit se terminer en son intégralité avant toute autre processus peut être échangé sur le PROCESSEUR.
donc je suppose que atomique dans ce cas signifie que les méthodes de lecteur d'attribut ne peuvent pas être interrompues - en effet, ce qui signifie que la ou les variables étant lues par la méthode ne peuvent pas changer leur valeur à mi-chemin parce qu'un autre thread/appel/fonction est échangé sur le CPU.
parce que les variables atomic
ne peuvent pas être interrompues, la valeur contenue par eux à tout moment est (thread-lock) garanti d'être non corrompu , bien que, en assurant ce thread lock rend l'accès à eux plus lent. Les variables non-atomic
, en revanche, ne garantissent pas une telle garantie mais offrent le luxe d'un accès plus rapide. Pour résumer, allez avec non-atomic
quand vous savez que vos variables ne seront pas accessibles par plusieurs threads simultanément et d'accélérer les choses.
après avoir lu tant d'articles, empiler des poteaux de débordement et faire des applications de démonstration pour vérifier les attributs de propriétés variables, j'ai décidé de mettre toutes les informations d'attributs ensemble:
-
atomic
// par défaut -
nonatomic
-
strong = retain
// par Défaut -
weak = unsafe_unretained
-
retain
-
assign
// par Défaut -
unsafe_unretained
-
copy
-
readonly
-
readwrite
// par Défaut
dans l'article attributs ou modificateurs de propriété variables dans iOS vous pouvez trouver tous les attributs mentionnés ci-dessus, et qui seront certainement vous aider.
-
atomic
-
atomic
désigne un seul thread accédant à la variable (de type statique). -
atomic
est thread-safe. - mais il est lent dans la performance
-
atomic
est le comportement par défaut - accessoires atomiques dans un environnement non collecté lors de l'utilisation de retain/release/autorelease) utilisera une serrure pour s'assurer qu'un autre thread n'interfère pas avec le bon réglage/obtention de la valeur.
- ce n'est pas vraiment un mot-clé.
exemple:
@property (retain) NSString *name; @synthesize name;
-
-
nonatomic
-
nonatomic
accès thread multiple à la variable (type dynamique). -
nonatomic
est thread-dangereux. - mais il est rapide dans la performance
-
nonatomic
n'est pas un comportement par défaut. Nous devons ajouter le mot-clénonatomic
dans l'attribut de propriété. - il peut en résulter un comportement inattendu, lorsque deux processus (threads) différents accèdent à la même variable en même temps.
exemple:
@property (nonatomic, retain) NSString *name; @synthesize name;
-
la réponse la plus facile d'abord: il n'y a pas de différence entre vos deux exemples. Par défaut, les accesseurs de propriété sont atomiques.
accesseurs atomiques dans un environnement non poubelle (c.-à-d. lors de l'utilisation de conserver/rejeter/autorelease) utilisera une serrure pour s'assurer qu'un autre fil n'interfère pas avec le bon réglage/obtention de la valeur.
voir la" Performance and Threading " section de L'objectif D'Apple - C 2.0 documentation pour plus d'informations et pour d'autres considérations lors de la création d'applications multi-threadées.
Atomique :
atomique garantit que l'accès à la propriété sera effectué de manière atomique. Par exemple: il renvoie toujours un objet entièrement initialisé, tout get / set d'une propriété sur un thread doit être complet avant qu'une autre puisse y accéder.
si vous imaginez la fonction suivante se produire sur deux threads à la fois, vous pouvez voir pourquoi les résultats ne seraient pas joli.
-(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;
}
...
}
Points forts: Le retour d'objets entièrement initialisés à chaque fois fait le meilleur choix en cas de multi-threading.
Inconvénients : Performance hit, rend l'exécution un peu plus lente
Non-Atomiques:
contrairement à Atomic, il ne garantit pas un retour d'objet entièrement initialisé à chaque fois.
Pour : Exécution extrêmement rapide.
Inconvénients : Les Chances de valeur des déchets en cas de multi-threading.
atomique signifie qu'un seul thread accède à la variable (de type statique). Atomic est sans fil, mais il est lent.
Nonatomique signifie plusieurs threads accédant à la variable (type dynamique). Nonatomic est thread-dangereux, mais il est rapide.
Atomic est thread safe , il est slow et il well-assures (not guaranteed) que seule la valeur verrouillée est fournie peu importe combien de threads tentent d'accéder au-dessus de la même zone. En utilisant atomic, un morceau de code écrit à l'intérieur de cette fonction devient la partie de la section critique, à laquelle seul un thread peut s'exécuter à la fois.
assure seulement la sécurité du fil; il ne garantir que. ce que je veux dire c'est que vous engagez un conducteur expert pour votre voiture, mais cela ne garantit pas que la voiture ne rencontrera pas un accident. Cependant, la probabilité reste la moindre.
atomique-il ne peut pas être décomposé, donc le résultat est attendu. Avec nonatomic-quand un autre thread accède à la zone mémoire, il peut le modifier, de sorte que le résultat est inattendu.
Code De Parler :
Atomique faire des getter et setter de la propriété thread-safe. par exemple si u a écrit:
self.myProperty = value;
est sans fil.
[myArray addObject:@"Abc"]
n'est pas sans fil.
il n'existe pas de mot-clé "atomique
@property(atomic, retain) UITextField *userName;
nous pouvons utiliser ce qui précède comme
@property(retain) UITextField *userName;
Voir Débordement de Pile question je reçois des questions si j'utilise @property(atomique,conserver)NSString *machaine .
le par défaut est atomic
, cela signifie qu'il ne vous coûte la performance chaque fois que vous utilisez la propriété, mais il est thread sûr. Ce que fait Objective-C, est de définir une serrure, de sorte que seul le thread actuel peut accéder à la variable, tant que le setter/getter est exécuté.
exemple avec MRC d'une propriété à usage interne:
[_internal lock]; //lock
id result = [[value retain] autorelease];
[_internal unlock];
return result;
donc ces deux derniers sont les mêmes:
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName; // defaults to atomic
sur l'autre main fait nonatomic
n'ajoute rien à votre code. Il n'est donc sûr que si vous codez le mécanisme de sécurité vous-même.
@property(nonatomic, retain) UITextField *userName;
les mots-clés ne doivent pas être écrits en tant que premier attribut de propriété du tout.
N'oubliez pas, cela ne signifie pas que la propriété dans son ensemble est thread-safe. Seul l'appel de méthode du setter/getter est. Mais si vous utilisez un setter et après une lecture à la même fois avec 2 threads différents, il pourrait être cassé aussi!
atomique (par défaut)
Atomique est la valeur par défaut: si vous ne tapez rien, votre propriété est atomique. Une propriété atomique est garantie que si vous essayez de lire à partir c', vous obtiendrez une valeur valide. Il ne donne aucune garantie sur ce que cette valeur pourrait être, mais vous obtiendrez en retour de bonnes données, pas juste ordure de la mémoire. Ce que cela vous permet de le faire est si vous avez plusieurs fils ou processus multiples pointant vers une seule variable, une le fil peut lire et un autre fil peut écrire. S'ils frappent en même temps temps, le fil de lecture est garanti pour obtenir une des deux valeurs: avant le changement ou après le changement. Ce atomique n'a pas vous donner est d'aucune garantie au sujet de laquelle de ces valeurs vous pourriez obtenir. Atomic est vraiment couramment confondu avec étant fil-safe, et ce n'est pas correct. Vous devez garantir la sécurité de votre filetage d'autres moyens. Cependant, atomique sera garantie que si vous essayez de lire, vous obtenez dos une sorte de valeur.
nonatomique
de l'autre côté, non-atomique, comme vous pouvez probablement deviner, signifie Juste, "ne fais pas ça atomique choses."Ce que vous perdez, c'est cette garantie que vous toujours récupérer quelque chose. Si vous essayez de lire au milieu d'un écrire, vous pourriez récupérer des données incorrectes. Mais, d'autre part, vous allez un peu plus vite. Parce que les propriétés atomiques doivent faire un peu de magie pour garantir que vous récupérez une valeur, ils sont un peu plus lent. Si c'est une propriété que vous accédez à un lot, vous pouvez déposer down to nonatomic pour s'assurer que vous n'avez pas cette vitesse pénalité.
voir plus ici: https://realm.io/news/tmi-objective-c-property-attributes /
avant de discuter des attributs de @property, vous devriez savoir à quoi sert @property. @property offre une façon de définir l'information qu'une classe est destinée à encapsuler. Si vous déclarez un objet/variable en utilisant @property, alors cet objet / variable sera accessible aux autres classes qui importent sa classe. Si vous déclarez un objet en utilisant @property dans le fichier d'en-tête, alors vous devez le synthétiser en utilisant @synthize dans le fichier d'implémentation.
exemple:
.classe H
@interface ExampleClass : NSObject
@property (nonatomic, retain) NSString *name;
@end
.Classe m
@implementation ExampleClass
@synthesize name;
@end
maintenant le compilateur va synthétiser les méthodes accessor pour le nom.
ExampleClass *newObject=[[ExampleClass alloc]init];
NSString *name1=[newObject name]; // get 'name'
[obj setName:@“Tiger”];
liste des attributs de @property : atomique. nonatomic. conserver. copie. ReadOnly. readwrite. assigner. fort.
atomique : C'est le comportement par défaut. Si un objet est déclaré comme atomique, puis il devient thread-safe. Thread-safe signifie, à la fois, qu'un seul thread d'une instance particulière de cette classe peut avoir le contrôle sur cet objet.
exemple:
@property NSString *name; //by default atomic
@property (atomic)NSString *name; // explicitly declared atomic
nonatomic: Il n'est pas thread-safe. Vous pouvez utiliser l'attribut de propriété non atomique pour spécifier que les accesseurs synthétisés peuvent simplement définir ou retourner une valeur directement, sans aucune garantie sur ce qui se passe si cette même valeur est consultée simultanément à partir de différents threads. Pour cette raison, il est plus rapide pour accéder à une propriété non atomique qu'une propriété atomique.
@property (nonatomic)NSString *name;
conserver: est requis lorsque l'attribut est un pointeur vers un objet.La méthode setter augmentera conserver compter de l'objet, de sorte qu'il occupera de la mémoire dans l'autorelease pool.
@property (retain)NSString *name;
copie: si vous utilisez la copie, vous ne pouvez pas utiliser la conservation. Utiliser l'instance de copie de la classe contiendra sa propre copie. Même si une chaîne mutable est définie et changée, l'instance capture quelle que soit la valeur qu'elle a au moment où elle est définie. Aucune méthode setter et getter ne sera synthétisée.
@property (copy) NSString *name;
NSMutableString *nameString = [NSMutableString stringWithString:@"Liza"];
xyzObj.name = nameString;
[nameString appendString:@"Pizza"];
readonly: si vous ne voulez pas permettre que la propriété soit changée via la méthode setter, vous pouvez déclarer la propriété readonly.
@property (readonly) NSString *name;
readwrite: est le comportement par défaut. Vous n'avez pas besoin de spécifier l'attribut readwrite explicitement.
@property (readwrite) NSString *name;
attribuer: va génère un setter qui assigne la valeur à la variable d'instance directement, plutôt que de la copier ou la retenir. C'est mieux pour les types primitifs comme NSInteger et CGFloat, ou les objets que vous ne possédez pas directement, comme les délégués.
@property (assign) NSInteger year;
forts: c'est un remplacement pour le conserver.
@property (nonatomic, strong) AVPlayer *player;
unsafe_unretained: il y a quelques classes dans le cacao et le cacao Touch qui ne supportent pas encore les références faibles, qui signifie que vous ne pouvez pas déclarer une propriété faible ou une variable locale faible pour garder une trace d'eux. Ces classes comprennent Ntextview, NSFont et NSColorSpace,etc. Si vous avez besoin d'utiliser une faible référence à l'une de ces classes, vous devez utiliser un dangereux référence. Une référence non sécuritaire est similaire à une référence faible en ce sens qu'elle ne garde pas son objet apparenté vivant, mais elle ne sera pas réglée à zéro si l'objet destination est désallocé.
@property (unsafe_unretained) NSObject *unsafeProperty;
si vous utilisez votre propriété en code multi-threadé, vous pourrez voir la différence entre les attributs non atomiques et atomiques. Le nonatomique est plus rapide que l'atomique et l'atomique est sans fil, pas le nonatomique.
Vijayendra Tripathi a déjà donné un exemple pour un environnement multi-threadé.
- -Atomic signifie un seul thread accédant à la variable(type statique).
- -Atomique est thread-safe.
- - mais il est lent dans la performance
comment déclarer:
Comme atomique est valeur par défaut donc,
@property (retain) NSString *name;
et dans le fichier de mise en œuvre
self.name = @"sourov";
supposons qu'une tâche liée à trois propriétés soit
@property (retain) NSString *name;
@property (retain) NSString *A;
@property (retain) NSString *B;
self.name = @"sourov";
toutes les propriétés fonctionnent en parallèle (comme asynchrone).
si vous appelez "nom" à partir du fil A ,
et
En même temps, si vous appelez
[self setName:@"Datta"]
à partir de fils B ,
Maintenant, Si *le nom de la propriété est nonatomic puis
- Il sera de retour la valeur "Datta" pour Un
- il retournera la valeur "Datta" pour B
"C'est pourquoi Non atomique est appelé thread dangereux, mais mais il est rapide dans la performance en raison de l'exécution parallèle
Maintenant, Si *le nom de la propriété est atomique
- Elle permettra de s'assurer de la valeur "Sourov" pour Un
- puis il retournera la valeur "Datta" pour B
c'est pourquoi atomic est appelé sans fil et C'est pour ça qu'on l'appelle read-write safe
une telle opération de situation se déroulera en série. Et Lent en performance
- Nonatomic-à-dire plusieurs thread accéder à la variable(de type dynamique).
- Nonatomic est thread dangereux.
- mais il est rapide dans la performance
-Nonatomic n'est PAS le comportement par défaut, nous avons besoin d'ajouter nonatomic mot-clé dans la propriété de l'attribut.
Pour En Swift Confirmant que les propriétés de Swift sont non atomiques au sens D'ObjC. Une raison est donc vous pensez à savoir si l'atomicité par propriété est suffisante pour vos besoins.
référence: https://forums.developer.apple.com/thread/25642
Fro plus d'informations s'il vous plaît visitez le site web http://rdcworld-iphone.blogspot.in/2012/12/variable-property-attributes-or.html
avant de commencer: vous devez savoir que chaque objet dans la mémoire doit être retiré de la mémoire pour qu'une nouvelle écriture se produise. Vous ne pouvez pas simplement écrire sur quelque chose comme vous le faites sur le papier. Vous doit d'abord l'effacer (dealloc) et ensuite vous pouvez écrire dessus. Si au moment où l'effacement est fait (ou la moitié fait) et rien a encore a été écrit (ou la moitié a écrit) et vous essayez de lire il pourrait être très problématique! Atomiques et non atomiques vous aider à traiter ce problème de différentes manières.
lire D'abord cette" question puis lire réponse de Bbum . En outre, puis lire mon résumé.
atomic
garantira toujours
- si deux personnes différentes veulent lire et écrire en même temps, votre papier ne brûlera pas! --> Votre demande ne jamais s'écraser, même dans un État de course.
- si une personne essaie d'écrire et n'a écrit que 4 des 8 lettres à written, alors aucune ne peut lire au milieu, la lecture ne peut être faite que lorsque les 8 lettres sont écrites --> aucune lecture(get) n'aura lieu sur 'un thread qui est encore en train d'écrire', c.-à-d. s'il y a 8 bytes aux bytes à écrire, et seulement 4 bytes sont écrits--jusqu'à ce moment, vous n'êtes pas autorisé à lire à partir de celui-ci. Mais comme j'ai dit qu'il ne s'écraserait pas alors il lirait de la valeur d'un objet autoreleased .
- si avant vous écrivant ont effacé ce qui a été précédemment écrit sur le papier et alors quelqu'un veut vous lire can encore lire. Comment? Vous lirez à partir de quelque chose de similaire à Mac OS poubelle (comme poubelle N'est pas encore 100% effacé...il est dans un limbo) - - - > si ThreadA est à lire alors que ThreadB a déjà été attribué à write, vous pouvez soit obtenir la valeur de la valeur finale entièrement écrite par ThreadB ou obtenir quelque chose de autorelease pool.
Conserver les comptes sont la façon dont la mémoire est gérée en Objective-C. Lorsque vous créez un objet, il a conserver un nombre de 1. Lorsque vous envoyez un objet conserver un message, conserver son compteur est incrémenté de 1. Lorsque vous envoyez un objet, un message de libération, conserver son compteur est décrémenté par 1. Lorsque vous envoyez un l'objet d'une autorelease message , ses conserver le comte est décrémenté de 1 à un certain moment dans l'avenir. Si un object's conserver nombre est réduit à 0, il est libéré.
- Atomic doesn't garantir la sécurité du fil, bien que son utile pour atteindre la sécurité du fil. La sécurité du fil est relative à la façon dont vous écrivez votre code/ quelle file d'attente de fil vous lisez/écrivez. Il garantit seulement non-crashable multithreading.
attendre quoi?! Est-ce que multithreading et thread safety sont différents?
Oui. Multithreading signifie: plusieurs threads peuvent lire un morceau de données partagées en même temps et nous ne nous écraserons pas, mais cela ne garantit pas que vous ne lisez pas à partir d'une valeur non autoreleased. Avec la sécurité de fil, il est garanti que ce que vous lisez n'est pas auto-relâché. La raison pour laquelle nous ne faisons pas tout atomique par défaut est, parce qu'il ya un coût de performance et pour la plupart des choses n'ont pas vraiment besoin de la sécurité du fil. Quelques parties de notre code en ont besoin et pour ces quelques parties nous avons besoin d'écrire notre code d'une manière sûre en utilisant des serrures, du mutex ou de la synchronisation.
nonatomic
- Puisqu'il n'y a pas de poubelle Mac OS, alors personne ne se soucie de savoir si oui ou non vous obtenez toujours une valeur (<-- cela pourrait potentiellement conduire à un crash), ni personne ne se soucie si quelqu'un essaie de lire à mi-chemin à travers vous en écrivant (bien que l'écriture à mi-chemin dans la mémoire est très différente de l'écriture à mi-chemin sur le papier, sur la mémoire il pourrait vous donner une valeur stupide folle d'avant, tandis que sur le papier vous ne voyez que la moitié de ce qui a été écrit) --> ne garantit pas de ne pas crash, parce qu'il n'utilise pas de mécanisme autorelease.
- N'est pas garantie des valeurs écrites complètes à lire!
- est plus rapide qu'atomique
dans l'ensemble, ils sont différents en deux points:
-
S'écraser ou non à cause d'avoir ou de ne pas avoir autorelease pool.
-
permettant d'être lu en plein milieu d'une "écriture pas encore terminée ou valeur vide" ou ne permettant pas et seulement permettant de lire lorsque la valeur est entièrement écrit.
la propriété atomique garantit de conserver une valeur entièrement initialisée indépendamment du nombre de threads qui y font getter & setter.
la propriété nonatomique spécifie que les accesseurs synthétisés ne font que définir ou retourner une valeur directement, sans aucune garantie sur ce qui se passe si cette même valeur est accessible simultanément à partir de différents threads.
Atomique signifie qu'un seul thread peut accéder à la variable à la fois (de type statique). Atomic est sans fil, mais il est lent.
Nonatomique signifie que plusieurs threads peuvent accéder à la variable en même temps (type dynamique). Nonatomic est thread-dangereux, mais il est rapide.
si vous utilisez atomic, cela signifie que le fil sera sûr et en lecture seule. Si vous utilisez nonatomic, cela signifie que les threads multiples accèdent à la variable et est thread dangereux, mais il est exécuté rapidement, fait une lecture et des opérations d'écriture; c'est un type dynamique.
Atomic: assurer la sécurité du thread en verrouillant le thread à l'aide de NSLOCK.
Non atomique: ne garantit pas la sécurité du thread car il n'y a pas de mécanisme de verrouillage du thread.
pour simplifier toute la confusion laissez-nous comprendre serrure mutex.Mutex lock comme par le nom des verrous de la mutabilité de l'objet.Donc, si l'objet est accessible par une classe d'aucune autre classe peuvent accéder au même objet.Dans iOS @sychronise également fournir le mutex lock.Maintenant il sert en mode FIFO et assure que le flux n'est pas affecté par deux classes partageant la même instance.Cependant, si la tâche est sur le thread principal, évitez d'accéder à l'objet en utilisant des propriétés atomiques car il peut contenir votre UI et dégrader le performance
la vérité est qu'ils utilisent spin lock pour mettre en œuvre la propriété atomique. Le code suivant:
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);
}
propriétés Atomiques :- Lorsqu'une variable est assignée propriété de l'atome qui signifie qu'il n'a qu'un seul thread d'accès et il va être thread-safe et sera bien en vue des performances, aura le comportement par défaut.
Non Propriétés Atomiques :- Lorsqu'une variable est assignée propriété de l'atome qui signifie qu'il a multi thread d'accès et il ne sera pas thread-safe et sera lente au point de vue des performances, aura comportement par défaut et lorsque deux threads différents veulent accéder à la variable en même temps, il donnera des résultats inattendus.