ios - une - openclassroom forme normale




Quelle est la différence entre les attributs atomiques et non atomiques? (18)

Que signifient les nonatomic atomic et nonatomic atomic dans les déclarations de propriété?

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

Quelle est la différence opérationnelle entre ces trois?


atomique (par défaut)

Atomic 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 d'en lire, vous obtiendrez une valeur valide. Cela ne donne aucune garantie quant à la valeur de cette valeur, mais vous obtiendrez de bonnes données, pas seulement de la mémoire indésirable. Ce que cela vous permet de faire est si vous avez plusieurs threads ou plusieurs processus pointant vers une seule variable, un thread peut lire et un autre thread peut écrire. Si elles frappent en même temps, le thread du lecteur est garanti d'obtenir l'une des deux valeurs: soit avant le changement ou après le changement. Ce que l'atomique ne vous donne pas est une sorte de garantie sur laquelle de ces valeurs vous pourriez obtenir. Atomic est souvent confondu avec thread-safe, et ce n'est pas correct. Vous devez garantir votre sécurité de thread d'autres façons. Cependant, atomic garantira que si vous essayez de lire, vous récupérez une sorte de valeur.

non atomique

D'un autre côté, non atomique, comme vous pouvez probablement le deviner, signifie simplement «ne faites pas ce truc atomique». Ce que vous perdez, c'est la garantie que vous récupérez toujours quelque chose. Si vous essayez de lire au milieu d'une écriture, vous pouvez récupérer les données de vidage. Mais, d'un autre côté, 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érerez une valeur, elles sont un peu plus lentes. Si c'est une propriété à laquelle vous avez beaucoup accès, vous voudrez peut-être passer à Nonatomic pour vous assurer que vous n'encourez pas cette pénalité de vitesse.

Voir plus ici: https://realm.io/news/tmi-objective-c-property-attributes/


Atomique

Atomic garantit que l'accès à la propriété sera effectuée de manière atomique. Par exemple, il retourne toujours un objet entièrement initialisé, tout get / set d'une propriété sur un thread doit se terminer avant qu'un autre puisse y accéder.

Si vous imaginez la fonction suivante se produisant sur deux threads à la fois, vous pouvez voir pourquoi les résultats ne seraient pas jolis.

-(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;
  }

  ...
}

Avantages: Le retour des 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-Atomique:

Contrairement à Atomic, il ne garantit pas le retour de l'objet entièrement initialisé à chaque fois.

Avantages: Exécution extrêmement rapide.

Inconvénients: Les chances de la valeur des ordures en cas de multi-threading.


Après avoir lu tant d'articles, affiche et fait des applications de démonstration pour vérifier les attributs des propriétés des variables, j'ai décidé de mettre toutes les informations d'attributs ensemble:

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

Dans l'article Attributs de propriété de variable ou modificateurs dans iOS, vous pouvez trouver tous les attributs mentionnés ci-dessus, et cela va certainement vous aider.

  1. atomic

    • atomic signifie qu'un seul thread accède à la variable (type statique).
    • atomic est thread safe.
    • Mais il est lent en performance
    • atomic est le comportement par défaut
    • Les accesseurs atomiques dans un environnement non garbage collect (c'est-à-dire lors de l'utilisation de retain / release / autorelease) utiliseront un verrou pour s'assurer qu'un autre thread n'interfère pas avec le réglage / l'obtention de la valeur correcte.
    • Ce n'est pas réellement un mot-clé.

    Exemple:

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

    • nonatomic signifie que plusieurs threads accèdent à la variable (type dynamique).
    • nonatomic est thread-dangereux.
    • Mais c'est rapide en performance
    • nonatomic n'est PAS un comportement par défaut. Nous devons ajouter le mot clé nonatomic dans l'attribut de propriété.
    • Cela peut entraîner un comportement inattendu, lorsque deux processus différents (threads) accèdent à la même variable en même temps.

    Exemple:

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

Atomic est thread-safe , il est lent et il assure (pas garanti) que seule la valeur verrouillée est fournie quel que soit le nombre de threads qui tentent d'accéder sur la même zone. Lorsque vous utilisez atomic, un morceau de code écrit à l'intérieur de cette fonction devient la partie de la section critique, à laquelle un seul thread peut s'exécuter à la fois.

Il assure seulement la sécurité de filetage; cela ne garantit pas cela. Ce que je veux dire, c'est que vous embaucher un chauffeur expert pour votre voiture, mais il 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, le résultat est inattendu.

Code Talk:

Atomic rend le getter et le setter de la propriété threads sûrs. par exemple si vous avez écrit:

self.myProperty = value;

est thread safe.

[myArray addObject:@"Abc"] 

n'est PAS thread safe.


Ceci est expliqué dans la documentation d'Apple, mais voici 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 atomique, mais spécifier "atomic" explicitement entraînera 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_;
    }
}

Fondamentalement, la version atomique doit prendre un verrou afin de garantir la sécurité du fil, et aussi cogner le compte ref sur l'objet (et le compte autorelease pour l'équilibrer) de sorte que l'objet est garanti pour l'appelant, sinon il est une condition de concurrence potentielle si un autre thread est en train de définir la valeur, entraînant la chute du nombre de ref à 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 interagissent retain, copy, readonly, nonatomic, etc. En général, les synthétiseurs de propriété savent juste faire la «bonne chose» pour toutes les combinaisons.


J'ai trouvé une explication assez bien posée des propriétés atomiques et non-atomiques here . Voici un texte pertinent de la même:

«atomique» signifie qu'il ne peut pas être décomposé. En termes d'OS / programmation, un appel de fonction atomique est un appel qui ne peut pas être interrompu - toute la fonction doit être exécutée, et non échangée hors de la CPU par le changement de contexte habituel du système d'exploitation jusqu'à ce qu'il soit terminé. Juste au cas où vous ne le sauriez pas: puisque le CPU ne peut faire qu'une seule chose à la fois, le système d'exploitation tourne l'accès au processeur à tous les processus en cours dans des tranches de temps, pour donner l' illusion du multitâche. Le planificateur de CPU peut (et interrompt) un processus à n'importe quel moment de son exécution - même en cas d'appel de fonction moyenne. Ainsi, pour des actions comme la mise à jour de variables de comptage partagées où deux processus peuvent essayer de mettre à jour la variable en même temps, ils doivent être exécutés "atomiquement", c'est-à-dire que chaque action de mise à jour doit être terminée. CPU.

Donc, je devinerais que atomique dans ce cas signifie que les méthodes de lecture d'attributs ne peuvent pas être interrompues - ce qui signifie que les variables lues par la méthode ne peuvent pas changer leur valeur à mi-chemin parce qu'un autre thread / appel / fonction échangé sur le CPU.

Parce que les variables atomic ne peuvent pas être interrompues, la valeur qu'elles contiennent à tout moment est (thread-lock) garantie d'être non corrompue , bien que, en s'assurant que ce verrou thread rend leur accès plus lent. non-atomic autre côté, non-atomic variables non-atomic ne garantissent pas ce genre de choses 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 accélérer les choses.


La meilleure façon de comprendre la différence consiste à utiliser l'exemple suivant.

Supposons qu'il existe une propriété de chaîne atomique appelée "name", et si vous appelez [self setName:@"A"] du thread A, appelez [self setName:@"B"] du thread B, et appelez [self name] depuis thread C, alors toutes les opérations sur des threads différents seront effectuées en série, ce qui signifie que si un thread exécute un setter ou getter, alors d'autres threads attendent.

Cela rend la propriété "nom" sûre en lecture / écriture, mais si un autre thread, D, appelle [name release] simultanément, cette opération peut provoquer un plantage car il n'y a pas d'appel de setter / getter impliqué ici. Ce qui signifie qu'un objet est en lecture / écriture sécurisé (ATOMIC), mais pas thread-safe car un autre thread peut simultanément envoyer n'importe quel type de message à l'objet. Le développeur doit garantir la sécurité des threads pour de tels objets.

Si la propriété "nom" était non atomique, alors tous les threads de l'exemple ci-dessus - A, B, C et D s'exécuteront simultanément, produisant un résultat imprévisible. En cas d'atomique, l'un des deux A, B ou C s'exécutera en premier, mais D peut toujours s'exécuter en parallèle.


La réponse la plus simple en premier: Il n'y a pas de différence entre vos deux seconds exemples. Par défaut, les accesseurs de propriété sont atomiques.

Les accesseurs atomiques dans un environnement non garbage collect (c'est-à-dire lors de l'utilisation de retain / release / autorelease) utiliseront un verrou pour s'assurer qu'un autre thread n'interfère pas avec le réglage / l'obtention de la valeur correcte.

Consultez la section « Performance and Threading » de la documentation Objective-C 2.0 d'Apple pour plus d'informations et pour d'autres considérations lors de la création d'applications multithread.


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é uniquement par l'absence de nonatomic - atomic été ajouté comme mot-clé dans les versions récentes de llvm / clang).

En supposant que vous êtes @synthesizing les implémentations de la méthode, atomic vs non-atomique modifie le code généré. Si vous écrivez votre propre setter / getters, atomic / nonatomic / retain / assign / copy sont simplement consultatifs. (Note: @synthesize 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 également synthétisées automatiquement et seront ajoutées à leur nom pour empêcher un accès direct accidentel.

Avec "atomic", le setter / getter synthétisé veillera à ce qu'une valeur entière soit toujours renvoyée par le getter ou définie par le setter, indépendamment de l'activité du setter sur n'importe quel autre thread. C'est-à-dire que si le thread A est au milieu du getter alors que le thread B appelle le setter, une valeur viable réelle - un objet auto-libéré, très probablement - sera retournée à l'appelant dans A.

En nonatomic , aucune de ces garanties ne sont faites. Ainsi, non nonatomic est considérablement plus rapide que "atomique".

Qu'est-ce que "atomique" ne fait pas est de garantir la sécurité des threads. Si le thread A appelle le getter simultanément avec les threads B et C appelant le setter avec des valeurs différentes, le thread A peut récupérer l'une des trois valeurs renvoyées - celle précédant l'appel des setters ou l'une des valeurs passées dans les setters dans B et C. De même, l'objet peut finir avec la valeur de B ou C, aucun moyen de dire.

Assurer l'intégrité des données - l'un des principaux défis de la programmation multithread - est réalisé par d'autres moyens.

Ajoutant à ceci:

atomicity d'une seule propriété ne peut pas non plus garantir la sécurité des threads lorsque plusieurs propriétés dépendantes sont en jeu.

Considérer:

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

Dans ce cas, le thread A pourrait renommer l'objet en appelant setFirstName: puis en appelant setLastName: En attendant, le thread B peut appeler fullName entre les deux appels du thread A et recevra le nouveau prénom couplé avec l'ancien nom.

Pour y remédier, vous avez besoin d'un modèle transactionnel . C'est-à-dire un autre type de synchronisation et / ou d'exclusion qui permet d'exclure l'accès à fullName pendant la mise à jour des propriétés dépendantes.


Si vous utilisez votre propriété dans du code multithread, vous pourrez voir la différence entre les attributs non atomiques et atomiques. Nonatomic est plus rapide que atomique et atomique est thread-safe, pas nonatomic.

Vijayendra Tripathi a déjà donné un exemple pour un environnement multithread.


Atomique = sécurité du filetage

Non-atomique = Pas de sécurité de filetage

Sécurité du filetage:

Les variables d'instance sont thread-safe si elles se comportent correctement à partir de plusieurs threads, indépendamment de la planification ou de l'entrelacement de l'exécution de ces threads par l'environnement d'exécution et sans synchronisation supplémentaire ou autre coordination de la part du code appelant.

Dans notre contexte:

Si un thread modifie la valeur de l'instance, la valeur modifiée est disponible pour tous les threads, et un seul thread peut changer la valeur à la fois.

Où utiliser atomic :

si la variable d'instance est accessible dans un environnement multithread.

Implication de l' atomic :

Pas aussi vite que nonatomic parce que nonatomic n'exige aucun travail de surveillance sur cela de l'exécution.

Où utiliser nonatomic :

Si la variable d'instance ne va pas être modifiée par plusieurs threads, vous pouvez l'utiliser. Cela améliore les performances.



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

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


Before discussing about the attributes of @property, you should know what is the use of @property. @property offers a way to define the information that a class is intended to encapsulate. 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.

Exemple:

.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.

Exemple :

@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;


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.


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.


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


  • -Atomique signifie qu'un seul thread accède à la variable (type statique).
  • -Atomic est thread safe.
  • mais il est lent en performance

Comment déclarer:

Comme atomique est par défaut,

@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 parallèlement (comme de manière asynchrone).

Si vous appelez "nom" du fil A ,

Et

En même temps, si vous appelez

[self setName:@"Datta"]

à partir du fil B ,

Maintenant, si la propriété * name est non atomique, alors

  • Il retournera la valeur "Datta" pour A
  • Il retournera la valeur "Datta" pour B

C'est pourquoi le non-atomique est appelé thread dangereux mais il est rapide dans la performance en raison de l'exécution parallèle

Maintenant, si la propriété * name est atomique

  • Il va assurer la valeur "Sourov" pour A
  • Puis Il retournera la valeur "Datta" pour B

C'est pourquoi atomic est appelé thread Safe et c'est pourquoi il est appelé en lecture-écriture sûr

Une telle opération de situation fonctionnera en série. Et lent dans la performance

- Nonatomic signifie que plusieurs threads accèdent à la variable (type dynamique).

- Nonatomic est un fil dangereux.

- mais c'est rapide en performance

-Nonatomic n'est pas un comportement par défaut, nous devons ajouter un mot-clé nonatomic dans l'attribut de propriété.

Pour In Swift Confirmant que les propriétés Swift sont non atomiques dans le sens d'ObjC. Une raison est que vous pensez si l'atomicité par propriété est suffisante pour vos besoins.

Référence: https://forums.developer.apple.com/thread/25642

Pour plus d'informations s'il vous plaît visitez le site Web http://rdcworld-iphone.blogspot.in/2012/12/variable-property-attributes-or.html







atomic