La syntaxe et la sémantique sont déjà bien définies par d'autres excellentes réponses à cette question. Parce que exécution y performance ne sont pas bien détaillées, je vais ajouter ma réponse.
Quelle est la différence fonctionnelle entre ces trois-là ?
J'ai toujours considéré l'atomique comme un défaut assez curieux. Au niveau d'abstraction auquel nous travaillons, l'utilisation des propriétés atomiques d'une classe comme moyen d'obtenir une sécurité filaire à 100% est un cas limite. Pour des programmes multithreads vraiment corrects, l'intervention du programmeur est presque certainement nécessaire. En attendant, les caractéristiques de performance et l'exécution n'ont pas encore été détaillées en profondeur. Ayant écrit quelques programmes fortement multithreadés au cours des années, j'avais déclaré mes propriétés comme étant nonatomic
tout le temps parce que l'atome n'avait aucun sens. Pendant la discussion des détails des propriétés atomiques et non atomiques cette question j'ai fait un peu de profilage et j'ai rencontré des résultats curieux.
Exécution
Ok. La première chose que je voudrais clarifier est que l'implémentation du verrouillage est définie par l'implémentation et abstraite. Louis utilise @synchronized(self)
dans son exemple - j'ai constaté que c'était une source fréquente de confusion. L'implémentation ne en fait utiliser @synchronized(self)
il utilise le niveau de l'objet verrous tournants . L'illustration de Louis est bonne pour une illustration de haut niveau utilisant des constructions qui nous sont toutes familières, mais il est important de savoir qu'elle n'utilise pas @synchronized(self)
.
Une autre différence est que les propriétés atomiques conservent/libèrent le cycle de vos objets dans le getter.
Performance
Voici la partie intéressante : La performance en utilisant les accès atomiques aux propriétés dans incontesté (par exemple, en mode single-thread) peuvent être vraiment très rapides dans certains cas. Dans des cas moins qu'idéaux, l'utilisation d'accès atomiques peut coûter plus de 20 fois l'overhead de nonatomic
. Alors que le Contesté en utilisant 7 threads était 44 fois plus lent pour la structure à trois octets (2,2 GHz). Core i7 Quad Core, x86_64). La struct à trois octets est un exemple de propriété très lente.
Remarque 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, soit 84 % de la vitesse des accesseurs non atomiques synthétisés.
Les objets dans les affaires contestées 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 entendrez souvent quelque chose comme "Faites confiance, sauf si vous profilez et constatez que cela pose un problème". En raison du niveau d'abstraction, il est en fait assez difficile de mesurer l'impact réel. Le calcul des coûts réels à partir des profils peut prendre beaucoup de temps et, en raison des abstractions, être assez imprécis. De même, l'ARC et le MRC peuvent faire une grande différence.
Alors prenons du recul, no en se concentrant sur l'implémentation des accès aux propriétés, nous inclurons les suspects habituels tels que objc_msgSend
et examinons quelques résultats de haut niveau dans le monde réel pour de nombreux appels à un fichier de type NSString
dans incontesté cas (valeurs en secondes) :
- MRC | non atomique | récupérateurs implémentés manuellement : 2
- MRC | nonatomique | getter synthétisé : 7
- MRC | atomique | getter synthétisé : 47
- ARC | nonatomique | getter synthétisé : 38 (note : l'ARC ajoute un cycle de comptage des références ici)
- ARC | atomique | getter synthétisé : 47
Comme vous l'avez probablement deviné, l'activité de comptage des références/le cyclisme est un facteur important avec les atomiques et les sous ARC. On constate également des différences plus importantes dans les cas contestés.
Bien que je prête une attention particulière à la performance, je dis toujours La sémantique d'abord ! . Pendant ce temps, la performance est une faible priorité pour de nombreux projets. Cependant, connaître les détails d'exécution et les coûts des technologies que vous utilisez ne fait certainement pas de mal. Vous devez utiliser la bonne technologie en fonction de vos besoins, de vos objectifs et de vos capacités. Nous espérons que cela vous épargnera quelques heures de comparaisons et vous aidera à prendre une décision plus éclairée lors de la conception de vos programmes.
4 votes
developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/