Domanda:
Cosa, in realtà significa atomic e nonatomic quando dichiariamo una @property nel file di intestazione .h?
[code lang=”obj-c”]
@property(nonatomic, retain) UITextField *userName;
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName;
[/code]
Che differenza c’è tra queste tre dichiarazioni?
Risposta:
Gli ultimi due sono identici, “atomic” è il comportamento predefinito. Atomic è stato aggiunto come parola chiave nelle versioni recenti di LLVM / clang.
Dando per scontato che @synthesize le implementazioni dei metodi, tra atomica e non-atomica cambia il codice generato il codice generato. Se state scrivendo un setter / getter, atomic / nonatomic / retain / assign / copy sono meramente consultivo. (Nota: @synthesize è ora il comportamento di default nelle versioni recenti di LLVM non è necessario dichiarare le variabili di istanza, verranno sintetizzate automaticamente, e avranno un _ (underscore) davanti il proprio nome per evitare l’accesso diretto accidentale.
Con “atomic“, il setter / getter sintetizzato farà in modo che un valore venga sempre restituito dal getter o impostato dal setter, indipendentemente dall’attività su qualsiasi altro thread. Cioè, se thread A è nel bel mezzo del getter mentre il thread B chiama il setter, un valore vitale reale – un oggetto autoreleased, molto probabilmente – sarà restituito al chiamante in A.
In nonatomic , non c’è alcuna garanzia. In questo modo, nonatomic è notevolmente più veloce di “atomic”.
Ciò che atomic non fa è rendere sicuro l’accesso circa la sicurezza thread. Se il thread A chiama il getter contemporaneamente con thread B e C che chiamano il setter con valori diversi, il thread A può ottenere uno qualsiasi dei tre valori restituiti – quello prima che qualsiasi setter venga chiamato o uno dei valori passati nei setter in B e C. Allo stesso modo, l’oggetto può finire con il valore di B o C, non c’è modo di saperlo.
Garantire l’integrità dei dati – una delle sfide principali della programmazione multi-threaded – è ottenuto con altri mezzi.
Tutto questo viene spiegato nella documentazione Apple , ma di seguito riporto alcuni esempi di ciò che sta realmente accadendo. Nota che non vi è alcuna parola chiave atomic, se non si specifica nonatomic allora la proprietà è atomic, ma specificando atomica esplicitamente si tradurrà in un errore.
nonatomic
[code lang=”obj-c”]
//@property(nonatomic, retain) UITextField *userName;
– (UITextField *) userName {
return userName;
}
– (void) setUserName:(UITextField *)userName_ {
[userName_ retain];
[userName release];
userName = userName_;
}
[/code]
atomic
[code lang=”obj-c”]
//@property(retain) UITextField *userName;
– (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_;
}
}
[/code]