28 votes

Pourquoi "atomic" est-il un qualificatif @property par défaut en Objective C alors que je me retrouve à utiliser "nonatomic" 100% du temps ?

Au cours de mes quelques années en tant que développeur iOS, je ne pense pas avoir déjà utilisé atomique sur une propriété. Si je peux voir des conditions de course potentielles ou des problèmes d'intégrité des données en raison de l'utilisation de threads, l'utilisation de atomique sur un @propriété n'aiderait jamais. J'utilise des techniques conventionnelles de sécurité des transactions/unités de travail (en utilisant des mécanismes de verrouillage, des sémaphores ou autres).

Quelqu'un a-t-il (ou connaît-il) des exemples pratiques d'endroits où les atomique est utilisé ? (J'aimerais bien voir des exemples de codes réels/pratiques)

Après avoir écrit nonatomique pour la milliardième fois peut-être, je me demande aussi pourquoi Apple a décidé de faire de l'argent. atomique la valeur par défaut.

17voto

Tomas Vana Points 5686

Quant au premier problème que vous rencontrez, il est peut-être dû au fait que

Bien que le terme "atomique" signifie que l'accès à la propriété est sans risque pour les threads, le fait de rendre toutes les propriétés de votre classe atomiques ne signifie pas que votre classe ou, plus généralement, votre graphe d'objets est "sans risque pour les threads" - la sécurité pour les threads ne peut pas être exprimée au niveau des méthodes d'accès individuelles.

Quant à savoir pourquoi Apple le rend atomique par défaut, je ne pense pas qu'il y ait de bonne raison, c'était simplement une mauvaise décision de conception. Les personnes présentes lors des sessions WWDC ont encouragé à plusieurs reprises les gens à utiliser le nonatomique chaque fois que c'est possible pour éliminer l'impact sur les performances.

10voto

BJ Homer Points 29168

Il convient de noter que dans le cadre du ramassage des ordures, presque tous les accesseurs synthétisés sont intrinsèquement atomiques - il n'y aurait aucune différence entre la version atomique et non atomique, puisque la simple affectation d'un pointeur est tout ce qui est nécessaire dans les deux cas. Étant donné qu'il est impossible de créer un accesseur synthétisé non atomique dans le cadre du ramassage des ordures, il se peut que l'on ait décidé qu'il était plus logique que les choses soient atomiques par défaut.

Je n'ai pas la preuve que c'est le raisonnement qui a présidé à la décision, mais cela me semble logique.

(Au cas où vous seriez curieux, il existe encore des cas où, dans le cadre du ramassage des ordures, l'affectation simple est non atomique, ce qui se produit lorsque la valeur est supérieure à la taille du mot du processus. En pratique, cela n'arrive qu'avec les structures).

Edit : Ajout des sources

De plus amples informations sur l'atomicité des propriétés synthétisées dans le cadre du ramassage des ordures sont disponibles à l'adresse suivante Le langage de programmation Objective-C -> Propriétés déclarées -> Performance et threading où il est dit que "dans un environnement de collecte des déchets, la plupart des méthodes synthétisées sont atomiques sans encourir ce surcoût". L'atomicité inhérente est mentionnée plus explicitement dans la session 420 du WWDC 2008 "Using Garbage Collection with Objective-C", aux alentours de la 29e minute.

4voto

ennalax Points 166

En deux mots : sécurité des fils. La plupart des applications que nous écrivons régulièrement sont assez simples et, en tant que telles, bénéficieront de l'absence de verrous supplémentaires.


De la part d'Apple Le langage de programmation Objective-C :

Les propriétés sont atomiques par défaut, de sorte que les accesseurs synthétisés fournissent un accès robuste aux propriétés dans un environnement multithread, c'est-à-dire que la valeur renvoyée par le getter ou définie par le setter est toujours entièrement récupérée ou définie, quels que soient les autres threads qui s'exécutent simultanément. Pour plus de détails, voir " Performance et threading ."

Si vous ne spécifiez pas nonatomique, alors dans un environnement de comptage de références, un accesseur synthétisé pour une propriété d'objet utilise un verrou et conserve et libère automatiquement la valeur renvoyée - l'implémentation sera similaire à ce qui suit :

[_internal lock]; // lock using an object-level lock
id result = [[value retain] autorelease];
[_internal unlock];
return result;

Si vous spécifiez nonatomique, un accesseur synthétisé pour une propriété d'objet renvoie simplement la valeur directement.

3voto

JeremyP Points 46808

Lorsqu'Apple a introduit pour la première fois le concept de propriétés, la question de savoir si les propriétés pouvaient être utilisées à des fins commerciales a été largement débattue. atomic o nonatomic devrait être la règle par défaut et les atomistes ont gagné.

Je pense que le raisonnement est le suivant : dans un environnement threadé, à moins que la propriété ne soit atomique, vous ne pouvez pas garantir que le pointeur qu'elle renvoie est valide. Un getter non atomique serait implémenté de la manière suivante

-(MyObj*) someProperty
{
     return someInstVar;
}

Il est possible qu'un autre thread désalloue l'objet pointé par someInstVar après que le pointeur a été placé dans le registre de retour mais avant que l'appelant n'ait eu le temps de le conserver. Même cela n'est pas bon :

-(MyObj*) someProperty
{
     return [[someInstVar retain] autorelease];
}

parce qu'un autre thread pourrait désallouer un certainInstVar juste avant que le compte de conservation ne soit incrémenté.

La seule façon de renvoyer le pointeur en toute sécurité dans un environnement multithread est de procéder de la manière suivante :

-(MyObj*) someProperty
{
     @synchronized(self)
     {
         return [[someInstVar retain] autorelease];
     }
}

et de synchroniser également l'appareil de réglage.

Cependant, le problème est que le verrou est très coûteux (en réalité, ils ont utilisé quelque chose de beaucoup plus léger que @synchronized, mais c'est toujours coûteux), de sorte que tout le monde utilisait de toute façon des verrous non atomiques et le fait de rendre toutes les propriétés atomiques ne confère pas la sécurité des threads en général, de sorte que d'autres techniques sont nécessaires de toute façon et qu'elles tendent à éviter le problème dont j'ai parlé plus haut.

De nombreuses personnes pensent que la décision prise quant à la valeur par défaut n'est pas la bonne, mais elle ne peut pas être modifiée pour des raisons de rétrocompatibilité. Je me retrouve à taper nonatomic sans même y penser.

2voto

hipplar Points 3185

Les appels atomiques sont des appels qui ne peuvent pas être interrompus. L'appel doit être exécuté dans son intégralité.

La mise à jour de quelque chose comme une variable de compteur partagée serait quelque chose qui pourrait être atomique parce que vous ne voudriez pas que deux processus essaient d'accéder à la variable en même temps. Les actions doivent être exécutées de manière "atomique".

Il y a beaucoup d'informations utiles dans ce post de l'OS : Propriétés atomiques et non atomiques sur les différences et les problèmes de sécurité du fil de discussion entre atomique et non atomique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X