Thread-safe variables statiques objective c
Est-il une manière objective C que je peux définir un static int qui est thread-safe?
par exemple si j'ai de la classe appelée Session:
static unsigned int session_id = 1000;
- (int) generateSessionID{
return session_id++;
}
Je suis la construction d'objets de session à partir de threads différents, chaque objet session
doit avoir un id unique.
- Vous avez besoin d'utiliser une sorte de sémantique de verrouillage. Le problème est que vous voulez l'opération atomique. Mais gardez à l'esprit que "++" n'est pas atomique, c'est un peu d'opérations à la fois.
- est possible alors d'entourer mon retour session_id++ avec synchronisée(self){return session_id++}. Cependant, je ne suis pas sûr si cela va de verrouillage de la classe ou de l'objet lui-même.
- comme l'a écrit, il serait de verrouillage de l'instance, et non pas la classe (pas ce que vous voulez). Peut-être "
@synchronized([self class])
"? - Gelhar: non, ne pas synchroniser sur
[self class]
parce que les instances de sous-classes synchroniser sur différents objets de la classe. Synchroniser sur un explicite de la classe par exemple[MyClass class]
Vous devez vous connecter pour publier un commentaire.
Si vous parlez de Cacao, le mutex de fonctionnalités fournies par
NSLock
etNSRecursiveLock
.Afin de bien protéger les non-atomique de ressources, vous avez besoin de ces mutex, de peur que plusieurs threads peuvent essayer de changer les données en même temps (conduisant à la corruption) ou utiliser les données dans un demi-changé d'état (conduisant à des données non valides).
Votre code devrait ressembler à quelque chose comme ceci:
Si vous n'êtes pas à l'aide de Cacao (ou de ce que peu de Cacao en programmation je me souviens de mon bref intermède avec un iMac est donc le vague souvenir que c'est quasi inutile), il suffit d'utiliser le concept, de le traduire en quelque langue que ce soit cadre ou vous avez:
Expliquant que le dernier point de plus: si vous synchroniser sur
self
pour deux totalement sans rapport avec les choses (disons un ID de session et un ID d'utilisateur), ils vont bloquer les uns les autres malgré le fait qu'il n'est pas nécessaire de le faire. Je préfère deux mutex pour garder la granularité faible.Bien sûr, si vous avez seulement un mutex sur l'ID de session seul (mais voir ci-dessous pour la mise en garde), n'hésitez pas à utiliser
synchronized(self)
mais je préfère le faire à ma façon, je ne voudrais pas attraper de l'ajout d'une autre ressource protégée plus tard.En tout cas (c'est l'inconvénient mentionné), vous trouverez probablement que la synchronisation sur
self
ne serait pas protéger adéquatement une variable statique, ce qui serait partagé entre plusieurs objets. Le mutex doit appartenir à la données plutôt que tout ce qui est de l'utiliser.self
pour une méthode d'instance qui est de l'accès à une variable statique; peut-être la fonction de synchronisation de[self class]
, ou sur un objet qui est directement associée à la valeur en cours de modification (par exemple, envelopper les int dans un NSNumber et de synchronisation sur le NSNumber).+initialize method
(voir stackoverflow.com/questions/992070/...); mais une fois créé, il ne va pas loin.[MyClass class]
, pas[self class]
. Il semble @JeremyP dit[self class]
sera de retour un objet différent à chaque fois, pas un singleton.[self class]
retourne un objet différent à chaque fois. Il dit que si vous avez une sous-classe MySubclass qui hérite de Maclasse,[self class]
sera de retour[MySubclass class]
lorsqu'il est appelé à partir d'une instance deMySubclass
. C'est un argument valable.Je pense que vous feriez mieux de les utiliser les opérations atomiques de modifier
session_id
. Un question précédente parle atomique incrémenter/décrémenter les opérations pour OS X, et cette page parle de laOSAtomic
fichier d'en-tête. Les opérations atomiques sur des entiers, quelque chose qui est facilement le matériel pris en charge, sera probablement sensiblement plus rapide que d'utiliser le verrouillage de constructions.OSAtomicIncrement32
, qui sera à l'abri et ne pas avoir tous les frais généraux de Cacao ou POSIX primitives de synchronisation.Une réponse 4 ans plus tard, actuellement en iOS8. :o)
Le mieux pour moi est d'utiliser une classe singleton comme suit :
(monfichier.h)
=====================================================
(monfichier.m)
Vous avez juste besoin d'appeler la méthode 'generateSessionId" pour chaque nouvelle valeur de l'Id.
À l'aide de cette classe pour créer votre Id de session doit être assez loin je pense.
Espère que ça aidera les lecteurs de ce post. :o)
MODIFIER
Comme indiqué par certains lecteurs, la NSInteger "valeur" n'est pas thread-safe suivant ce chemin, seul le singleton est.
Pour obtenir un "thread-safe "valeur" variable d'instance juste changer sa NSInteger type dans NSNumber (pour être converti en int avec des méthodes appropriées) qui est complètement thread-safe selon la documentation d'Apple.
Ce peut être le plus simple et le plus rapide pour obtenir ce qui est désiré.
Il existe de nombreuses options, y compris (de haut niveau de plus bas niveau) le
@synchronized
Objective-C de la directive,NSLock
,pthread_mutex_lock
, et des opérations atomiques.Lire la "Synchronisation" de la Filetage Guide De Programmation pour plus de détails.