[Ios] Qual è la differenza tra gli attributi atomici e non anatomici?



Answers

Questo è spiegato nella documentation di Apple, ma di seguito sono riportati alcuni esempi di ciò che sta realmente accadendo. Si noti che non esiste una parola chiave "atomica", se non si specifica "nonatomico", la proprietà è atomica, ma specificando "atomico" esplicitamente si verificherà un errore.

//@property(nonatomic, retain) UITextField *userName;
//Generates roughly

- (UITextField *) userName {
    return userName;
}

- (void) setUserName:(UITextField *)userName_ {
    [userName_ retain];
    [userName release];
    userName = userName_;
}

Ora, la variante atomica è un po 'più complicata:

//@property(retain) UITextField *userName;
//Generates roughly

- (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_;
    }
}

Fondamentalmente, la versione atomica deve prendere un lock per garantire la sicurezza del thread, e anche il conteggio ref dell'oggetto (e il conteggio automatico per bilanciarlo) in modo che l'oggetto sia garantito per il chiamante, altrimenti lì è una potenziale condizione di competizione se un altro thread sta impostando il valore, facendo cadere il conteggio dei ref a 0.

Esistono in realtà un gran numero di diverse varianti di come funzionano queste cose a seconda che le proprietà siano valori o oggetti scalari e come interagire tra conservazione, copia, sola lettura, non anatomica, ecc. In generale i sintetizzatori di proprietà sanno solo come fare la "cosa giusta" per tutte le combinazioni.

Question

Che cosa significano atomic e non nonatomic nelle dichiarazioni di proprietà?

@property(nonatomic, retain) UITextField *userName;
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName;

Qual è la differenza operativa tra questi tre?




Atomico:

Atomic garantisce che l'accesso alla proprietà sarà eseguito in modo atomico. Ad esempio, restituisce sempre un oggetto completamente inizializzato, qualsiasi get / set di una proprietà su un thread deve essere completato prima che un altro possa accedervi.

Se si immagina che la seguente funzione che si verifica su due thread contemporaneamente, si possa capire perché i risultati non sarebbero belli.

-(void) setName:(NSString*)string
{
  if (name)
  {
    [name release]; 
    // what happens if the second thread jumps in now !?
    // name may be deleted, but our 'name' variable is still set!
    name = nil;
  }

  ...
}

Pro: il ritorno di oggetti completamente inizializzati ogni volta rende la scelta migliore in caso di multi-threading.

Contro: Colpo di prestazioni, rende l'esecuzione un po 'più lenta

Non Atomico:

A differenza di Atomic, non garantisce ogni volta il ritorno dell'oggetto completamente inizializzato.

Pro: esecuzione estremamente veloce.

Contro: Probabilità di valore spazzatura in caso di multi-threading.




The atomic property ensures to retain a fully initialised value irrespective of how many threads are doing getter & setter on it.

The nonatomic property specifies that synthesized accessors simply set or return a value directly, with no guarantees about what happens if that same value is accessed simultaneously from different threads.




Let's take an example:-

@property (atomic, strong) NSString *atomicProperty;
@property (nonatomic, strong) NSString *nonAtomicProperty;

Atomic Properties:-

1) Defining a property as atomic will guarantee that a valid value will be returned. Notice that valid does not always mean correct (more on that in the next section of this post)

2) Atomic properties suffer from the minor performance hit due to locking and unlocking before and after setting/getting a value.

3) Atomic is the default behavior for properties — this is what you get if you don't specify anything.

Non-Atomic Properties:-

1) Nonatomic properties have no guarantee regarding the returned value.

2) It can be the correct value, a partially written value or even some garbage value.

3) As most things that are not safe — this comes with an enhanced speed of accessing these properties.

Let's see how does the Objective-C runtime do this programmatically?

Let's look at the “set value” method for the Objective-C runtime.

Notice how nonatomic properties are directly setting the value of the property while an atomic property is using locks to protect the set operation




Before discussing about the attributes of @property, you should know what is the use of @property. @property offers a way to define the information that a class is intended to encapsulate. If you declare an object/variable using @property, then that object/variable will be accessible to other classes importing its class. If you declare an object using @property in the header file, then you have to synthesize it using @synthesize in the implementation file.

Esempio:

.h class

@interface ExampleClass : NSObject
   @property (nonatomic, retain) NSString *name;
@end

.m class

@implementation ExampleClass
   @synthesize name;
@end

Now the compiler will synthesize accessor methods for name.

ExampleClass *newObject=[[ExampleClass alloc]init];
NSString *name1=[newObject name]; // get 'name'
[obj setName:@“Tiger”];

List of attributes of @property : atomic. nonatomic. retain. copy. readonly. readwrite. assign. strong.

atomic : It is the default behaviour. If an object is declared as atomic then it becomes thread-safe. Thread-safe means, at a time only one thread of a particular instance of that class can have the control over that object.

Esempio :

@property NSString *name; //by default atomic
@property (atomic)NSString *name; // explicitly declared atomic

nonatomic: It is not thread-safe. You can use the nonatomic property attribute to specify that synthesized accessors simply set or return a value directly, with no guarantees about what happens if that same value is accessed simultaneously from different threads. For this reason, it's faster to access a nonatomic property than an atomic one. @property (nonatomic)NSString *name;

retain: is required when the attribute is a pointer to an object.The setter method will increase retain count of the object, so that it will occupy memory in autorelease pool. @property (retain)NSString *name;

copy: If you use copy, you can't use retain. Using copy instance of the class will contain its own copy. Even if a mutable string is set and subsequently changed, the instance captures whatever value it has at the time it is set. No setter and getter methods will be synthesized.

@property (copy) NSString *name;

NSMutableString *nameString = [NSMutableString stringWithString:@"Liza"];    
xyzObj.name = nameString;    
[nameString appendString:@"Pizza"];

readonly: If you don't want to allow the property to be changed via setter method, you can declare the property readonly. @property (readonly) NSString *name;

readwrite: is the default behaviour. You don't need to specify readwrite attribute explicitly.

@property (readwrite) NSString *name;

assign: will generate a setter which assigns the value to the instance variable directly, rather than copying or retaining it. This is best for primitive types like NSInteger and CGFloat, or objects you don't directly own, such as delegates.

@property (assign) NSInteger year;

strong: is a replacement for retain. @property (nonatomic, strong) AVPlayer *player;

unsafe_unretained: There are a few classes in Cocoa and Cocoa Touch that don't yet support weak references, which means you can't declare a weak property or weak local variable to keep track of them. These classes include NSTextView, NSFont and NSColorSpace,etc. If you need to use a weak reference to one of these classes, you must use an unsafe reference. An unsafe reference is similar to a weak reference in that it doesn't keep its related object alive, but it won't be set to nil if the destination object is deallocated.

@property (unsafe_unretained) NSObject *unsafeProperty;




Dopo aver letto tanti articoli, i messaggi e le applicazioni demo per controllare gli attributi delle proprietà variabili, ho deciso di mettere insieme tutte le informazioni sugli attributi:

  1. atomic // predefinito
  2. nonatomic
  3. strong = retain // Default
  4. weak = unsafe_unretained
  5. retain
  6. assign // Predefinito
  7. unsafe_unretained
  8. copy
  9. readonly
  10. readwrite // Predefinito

Nell'articolo Attributi o modificatori di proprietà variabili in iOS puoi trovare tutti gli attributi sopra menzionati e questo ti aiuterà sicuramente.

  1. atomic

    • atomic significa che solo un thread accede alla variabile (tipo statico).
    • atomic è thread sicuro.
    • Ma è lento nelle prestazioni
    • atomic è il comportamento predefinito
    • Gli accessor atomici in un ambiente non garbage collection (ossia quando si utilizza retain / release / autorelease) utilizzeranno un lock per assicurarsi che un altro thread non interferisca con l'impostazione / acquisizione corretta del valore.
    • In realtà non è una parola chiave.

    Esempio:

        @property (retain) NSString *name;
    
        @synthesize name;
    
  2. nonatomic

    • nonatomic significa accesso multiplo alla variabile (tipo dinamico).
    • nonatomic è sicuro per il thread.
    • Ma è veloce nelle prestazioni
    • nonatomic NON è un comportamento predefinito. Abbiamo bisogno di aggiungere la parola chiave non nonatomic nell'attributo della proprietà.
    • Può comportare un comportamento imprevisto quando due diversi processi (thread) accedono alla stessa variabile nello stesso momento.

    Esempio:

        @property (nonatomic, retain) NSString *name;
    
        @synthesize name;
    



To simplify the entire confusion let us understand mutex lock.Mutex lock as per the name locks the mutability of the object.So if the object is accessed by a class no other class can access the same object.In iOS @sychronise also provide the mutex lock.Now it serve in FIFO mode and ensures the flow is not affected by two classes sharing the same instance.However if the task is on main thread avoid accessing object using atomic properties as it may hold your UI and degrade the performance




Atomico = sicurezza del filo

Non atomico = Nessuna sicurezza del filo

Sicurezza filo:

Le variabili di istanza sono thread-safe se si comportano correttamente quando si accede da più thread, indipendentemente dalla pianificazione o interleaving dell'esecuzione di tali thread da parte dell'ambiente di runtime e senza sincronizzazione aggiuntiva o altro coordinamento sulla parte del codice chiamante.

Nel nostro contesto:

Se un thread modifica il valore dell'istanza, il valore modificato è disponibile per tutti i thread e solo un thread può modificare il valore alla volta.

Dove usare l' atomic :

se la variabile di istanza sarà accessibile in un ambiente con multithreading.

Implicazione di atomic :

Non veloce come non nonatomic perché nonatomic non richiede alcun lavoro di watchdog su quello da runtime.

Dove usare nonatomic :

Se la variabile di istanza non verrà modificata da più thread, puoi usarla. Migliora le prestazioni.




If you are using atomic, it means the thread will be safe and read-only. If you are using nonatomic, it means the multiple threads access the variable and is thread unsafe, but it is executed fast, done a read and write operations; this is a dynamic type.




Il valore predefinito è atomic , questo significa che ti costa la tua prestazione ogni volta che usi la proprietà, ma è thread-safe. Che cosa fa l'Objective-C, è impostato un lock, quindi solo la thread effettiva può accedere alla variabile, fintanto che il setter / getter viene eseguito.

Esempio con MRC di una proprietà con un ivar _internal:

[_internal lock]; //lock
id result = [[value retain] autorelease];
[_internal unlock];
return result;

Quindi questi ultimi due sono gli stessi:

@property(atomic, retain) UITextField *userName;

@property(retain) UITextField *userName; // defaults to atomic

D'altra parte nonatomic non aggiunge nulla al tuo codice. Quindi è sicuro solo se si codifica il meccanismo di sicurezza da soli.

@property(nonatomic, retain) UITextField *userName;

Le parole chiave non devono essere scritte come primo attributo di proprietà.

Non dimenticare, questo non significa che la proprietà nel suo insieme sia sicura per i thread. È solo la chiamata al metodo del setter / getter. Ma se usi un setter e dopo un getter allo stesso tempo con 2 thread diversi, potrebbe essere rotto anche tu!




Se stai usando la tua proprietà in codice multi-thread, allora sarai in grado di vedere la differenza tra attributi non atomici e atomici. Nonatomico è più veloce di atomico e atomico è thread-safe, non nonatomico.

Vijayendra Tripathi ha già dato un esempio per un ambiente multi-thread.




Atomic è thread-safe , è lento e garantisce (non è garantito) che solo il valore bloccato è fornito indipendentemente dal numero di thread che tentano di accedere alla stessa zona. Quando si utilizza atomico, un pezzo di codice scritto all'interno di questa funzione diventa la parte della sezione critica, alla quale può essere eseguito un solo thread alla volta.

Assicura solo la sicurezza del filo; non lo garantisce. Ciò che intendo è che noleggi un autista esperto per la tua auto, tuttavia non garantisce che la macchina non incontri un incidente. Tuttavia, la probabilità rimane la minima.

Atomico: non può essere scomposto, quindi il risultato è previsto. Con nonatomico - quando un altro thread accede alla zona della memoria, può modificarlo, quindi il risultato è inaspettato.

Discorso a codice:

Atomic rende sicuro getter e setter del thread di proprietà. per esempio se hai scritto:

self.myProperty = value;

è thread-safe

[myArray addObject:@"Abc"] 

NON è thread sicuro.




Il modo migliore per capire la differenza è usare il seguente esempio.

Supponiamo che ci sia una proprietà di stringa atomica chiamata "nome", e se chiami [self setName:@"A"] dal thread A, chiama [self setName:@"B"] dal thread B e chiama [self name] da thread C, quindi tutte le operazioni su thread diversi verranno eseguite in serie, il che significa che se un thread sta eseguendo un setter o un getter, allora altri thread attenderanno.

Questo rende la proprietà "nome" in lettura / scrittura sicura, ma se un altro thread, D, chiama [name release] contemporaneamente, questa operazione potrebbe causare un arresto anomalo perché non è presente alcuna chiamata setter / getter. Ciò significa che un oggetto è in lettura / scrittura sicuro (ATOMIC), ma non thread-safe poiché un altro thread può inviare contemporaneamente qualsiasi tipo di messaggio all'oggetto. Lo sviluppatore dovrebbe garantire la sicurezza del thread per tali oggetti.

Se il "nome" della proprietà era nonatomico, tutti i thread nell'esempio precedente - A, B, C e D verranno eseguiti simultaneamente producendo risultati imprevedibili. In caso di atomico, uno di A, B o C verrà eseguito per primo, ma D può ancora essere eseguito in parallelo.




Links