Le basi di Objective-C – @property atomic vs nonatomic

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:

nonatomic

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]