2012-09-10 13 views
27

Ho cercato e trovato immutable sono thread safe mentre mutable non lo è. Questo va bene. Ma ho delle note fuorvianti, dei blog, delle risposte atomiche e non atomiche sulla sicurezza dei thread, gentilmente do una spiegazione per la risposta.Qual è il thread-safe atomico o non atomico?

Supponiamo che ci sia una proprietà di stringa atomica denominata "nome", e se si chiama [self setName:@"A"] da filo A, chiamare [self setName:@"B"] da filo B, e chiamare [self name] da filo C, quindi tutte le operazioni sul thread diverso verrà eseguita in serie quali mezzi se un thread sta eseguendo setter o 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 poiché non è presente alcuna chiamata setter/getter. Il che 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.

Se il "nome" della proprietà non è di tipo anatomico, 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.

Distinti commento su questo ci aiuterà ....

E la mia domanda è, "che è thread-safe nel cacao, atomica o non-atomica?"

+2

http://www.google.com.ph/search?q = obiettivo + c + atomica + vs + nonatomic & aq = 0 & oq = obiettivo + c + atomica + vs + non & sugexp = cromo, mod = 10 & sourceid = cromo & ie = UTF-8 – janusbalatbat

risposta

61

Per objC Proprietà - Né sono sicuri thread.

Atomic è più resistente a agli errori di threading. Nel complesso, è un insolito insolito. Gli scenari che preferiresti agli atomici sono pochissimi. Atomico può aumentare la probabilità di correttezza, ma è troppo basso per essere considerato un sostituto per un meccanismo di bloccaggio adeguato. Pertanto, se hai bisogno di sicurezza del thread, hai ancora bisogno di qualche altra primitiva di sincronizzazione sopra le letture/scritture atomiche. Se non si ha bisogno della sicurezza del thread (ad esempio l'istanza è immutabile o destinata all'esecuzione solo dal thread principale), atomic non aggiungerà nulla.

Essere resistente a errori di threading non è una 'qualità' - serve a mascherare errori di threading reali e renderli più difficili da riprodurre e rilevare.

Si noti inoltre che i tipi mutabili e immutabili non garantiscono effettivamente la sicurezza del thread.'Mutabile' può essere usato nei nomi ObjC per riferirsi solo all'interfaccia - le parti interne di un'istanza immutabile possono effettivamente avere uno stato interno mutabile. In breve, non si può presumere che un tipo che ha una sottoclasse mutabile sia sicuro per i thread.


Domanda Expanded:

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

Se tutti i thread hanno tentato di leggere e/o scrivere nella proprietà contemporaneamente, solo un thread avrebbe accesso alla volta e gli altri sarebbero bloccati se la proprietà fosse atomica. Se la proprietà fosse non anatomica, allora tutti avrebbero accesso non controllato alla lettura e alla scrittura della variabile allo stesso "tempo".

se un altro thread D chiama [nome release] contemporaneamente, questa operazione potrebbe produrre un arresto anomalo perché non è presente alcuna chiamata setter/getter.

Corretto.

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.

Bene, c'è davvero molto di più. L'esempio comune è:

@interface MONPerson : NSObject 

    @property (copy) NSString * firstName; 
    @property (copy) NSString * lastName; 

    - (NSString *)fullName; 

    @end 

atomica o nonatomic, dovrai (ad esempio lock) un meccanismo di sincronizzazione se un thread sta leggendo da tale istanza e un altro sta scrivendo ad esso. Si può finire con una sola firstName di MONPerson e un altro è lastName - L'oggetto potrebbe essere cambiato prima che il valore di ritorno del getter è anche restituito a voi, o questo può accadere:

Discussione A:

p.firstName = @"Rob"; 

Discussione B :

p.firstName = @"Robert"; 

Discussione A:

label.string = p.firstName; // << uh, oh -- will be Robert 

Se il "nome" della proprietà non era anatomico, tutti i thread nell'esempio precedente - A, B, C e D verranno eseguiti simultaneamente producendo risultati imprevedibili.

I sintomi iniziali di destra possono essere squilibri di conteggio di riferimento (perdita, sovra-rilascio).

In caso di atomico, uno di A, B o C verrà eseguito per primo ma D può ancora essere eseguito in parallelo. Si prega di commentare questo ....

Corretto.Ma se si guarda all'esempio di cui sopra - solo atomico è raramente un sostituto adatto per una serratura. Si dovrebbe assomigliare a questo, invece:

Discussione A:

[p lock]; // << wait for it… … … … 
// Thread B now cannot access p 
p.firstName = @"Rob"; 
NSString fullName = p.fullName; 
[p unlock]; 
// Thread B can now access p 
label.string = fullName; 

Discussione B:

[p lock]; // << wait for it… … … … 
// Thread A now cannot access p 
… 
[p unlock]; 

di accesso Atomic possono media oltre venti volte più lento di accessi nonatomic. Inoltre, se la classe ha bisogno di essere protetta da thread e ha uno stato mutabile, è probabile che si utilizzi un blocco quando opera in uno scenario concorrente. Il blocco corretto fornisce tutte le garanzie di cui hai bisogno: gli accessor atomici sono ridondanti in tale scenario, l'uso di atomics aggiungerebbe solo il tempo della CPU. Un altro aspetto positivo del blocco regolare è che hai tutta la granularità di cui hai bisogno - anche se è spesso più pesante dello spin lock usato per gli atomici, in genere avrai bisogno di meno acquisizioni quindi sarà molto veloce se usi correttamente i blocchi regolari .

+0

Grazie per la descrizione in così tanto di dettagli, questo sicuramente aiuterà me e gli altri in là futuro cacao :) –

10

atomico garantisce l'accesso atomico alla variabile ma NON rende il thread del codice sicuro. Né non atomico.

Con "atomico", i metodi setter/getter sintetizzati assicurano che un valore intero venga sempre restituito dal getter o impostato dal setter, indipendentemente dall'attività del setter su qualsiasi altro thread. Quindi se il thread A si trova nel mezzo del getter mentre il thread B chiama il setter, verrà restituito al chiamante un valore effettivo valido in A. Per nonatomico, non si dispone di tali garanzie.

+0

Grazie Jeroen per la risposta. Quindi nessuno dei due, atomico e non atomico sono sicuri? –

+0

No, è come la mia risposta dice. Assicura solo che il getter restituisca valori che hanno senso in un ambiente multi-thread. – Asciiom

+0

Cosa significherebbe non ricevere un intero valore? Che tipo di errori vedrei? – powerj1984

-1

Si dovrebbe prendere in considerazione l'implementazione di un meccanismo di blocco in modo da non ottenere deadlock all'interno della vostra app. Inoltre, se stai implementando i dati del Core, dovresti leggere la sicurezza del thread iOS.

Vedere.

http://developer.apple.com/library/iOS/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html

http://developer.apple.com/library/iOS/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html%23//apple_ref/doc/uid/10000057i-CH8-SW1

+1

Grazie iris per la tua risposta. Sono consapevole di blocco e @synchronized, ma volevo solo da confermare su quale thread-safe e perché? –

+0

Atomic è thread-safe quando viene implementato correttamente, non atomica non è thread-safe e quindi è più veloce, ma non quando viene utilizzato con i filetti. – StackRunner

+0

aggiunta di un meccanismo di bloccaggio non impedirà bloccaporte. Può solo crearli. Penso che la parola "deadlock" potrebbe non significare cosa pensi che significhi. Con gli accessor "atomici", l'accesso stesso è thread-safe a un livello basso. Tuttavia, a un livello superiore è necessario rendere le cose thread safe te stesso. Nella domanda originale, con il thread A e B che imposta una variabile e il thread C che la legge, tutti e tre contemporaneamente, non atomici significa che l'operazione può bloccarsi. Atomico significa che non sai cosa verrà memorizzato e cosa leggerà C, ma non si bloccherà. – gnasher729

7

atomico rende sicuro il seguente thread.

self.myProperty = value; 

o

id value = self.myProperty 

non rende sicuro questo thread

[myPorperty addObject:value]; 

atomica rende thread-safe per impostare o ottenere una proprietà, ma non fa chiamare qualsiasi i metodi di quella proprietà sono thread-safe.

l'impostazione o il recupero dei valori può richiedere più di un'istruzione CPU e ciò significa che l'impostazione o il recupero possono essere interrotti a metà e un altro thread può fare qualcosa che impedisce l'avanzamento del thread precedente nell'impostazione o il valore.

atomico dice set o ottiene il valore in modo che accada come se fosse successo in una istruzione indivisibile e quindi nessun altro thread può intervenire a metà e rovinare tutto.

Gli oggetti immutabili sono thread-safe semplici perché non è possibile cambiarli, in quanto è possibile modificare una proprietà da un oggetto immutabile un altro in modo tale che la parte non sia sicura fino a quando non la si rende atomica.

1

C'è un'altra proprietà di "atomico" che non è stata menzionata che era necessaria per la sicurezza del thread prima di ARC (e probabilmente lo è ancora). Prima spieghiamo perché è necessario: Diciamo che senza ARC, si legge una proprietà dell'oggetto e la si conserva immediatamente. Ma un altro thread potrebbe entrare solo tra voi che leggete la proprietà e la chiamata di conservazione, impostate la proprietà dell'oggetto su zero, facendo sì che l'oggetto venisse deallocato. Si invia il retain a un oggetto deallocato, che non è sano. E sarebbe un errore molto raro, perché succede solo quando i tempi sono giusti. Per evitare ciò, le proprietà degli oggetti atomici restituiscono sempre oggetti autoreleased.

-6

Non atomico è thread-safe. Guranted ottiene il valore della variabile.