2010-02-14 4 views
7

Cosa succede quando due thread impostano un BOOL su YES "allo stesso tempo"?BOOL è in lettura/scrittura atomica nell'obiettivo C?

+16

si apre un wormhole in un'altra dimensione. – dreamlax

+5

Se sono entrambi impostazione a 'affermativa, non ci può essere un problema se la scrittura è atomica o no, può esistere? –

+0

@CarlNorum che potrebbe essere vero ma non è ovvio per me perché –

risposta

6

No. Senza un costrutto di bloccaggio, la lettura/scrittura di qualsiasi tipo variabile non è atomico in Objective C.

Se due thread scrivono YES contemporaneamente ad un BOOL, il risultato è SI, indipendentemente da quale si ottiene per primo.

consultare: Synchronizing Thread Execution

+2

Grazie, Mitch. ead lo imposta su SÌ, mentre un altro lo imposta su NO, può esserci corruzione della memoria? – Jacko

+1

http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html offre una discussione molto approfondita. Penso che userò un int invece di un BOOL e userò le operazioni OSAtomic su questo int. – Jacko

+0

L'implicazione della tua domanda è se qualche altro pezzo di memoria potrebbe essere scricchiolato o meno. No; questo non può accadere. Il peggio che accadrà è che leggerete un NO apparentemente dopo aver scritto un SI in un'altra discussione. – bbum

7

Ecco il codice per la soluzione suggerita da Jacko.
Usa volatileuint32_t con OSAtomicOr32Barrier e OSAtomicAnd32Barrier

#import <libkern/OSAtomic.h> 

volatile uint32_t _IsRunning; 

- (BOOL)isRunning { 
    return _IsRunning != 0; 
} 

- (void)setIsRunning:(BOOL)allowed { 

    if (allowed) { 
     OSAtomicOr32Barrier(1, & _IsRunning); //Atomic bitwise OR of two 32-bit values with barrier 
    } else { 
     OSAtomicAnd32Barrier(0, & _IsRunning); //Atomic bitwise AND of two 32-bit values with barrier. 
    } 
} 
+0

Cool! Ma perché non usare solo 'OSAtomicOr32Barrier (permesso, & _IsRunning); invece di istruzioni condizionali? –

+0

Sì, è possibile utilizzare. –

+0

Ah, non è così semplice, mi dispiace. Non è possibile utilizzare "o" versione per reimpostare il flag, ad esempio, è necessario utilizzare "e" la versione per eseguire questa operazione (OSAtomicAnd32Barrier). –

3

avrei dovuto divergere dalla risposta accettata. Scusate. Mentre l'obiettivo c non garantisce che le proprietà BOOL dichiarate come non anatomiche siano in realtà atomiche, dovrei indovinare che l'hardware a cui si è maggiormente interessati (tutti i dispositivi iOS e macOS) ha istruzioni per eseguire letture e archivi atomici. Quindi, a meno che Apple non utilizzi il sistema operativo Road Light con su un microcontrollore IBM con bus a 5 bit per inviare 10 bit byte su , è possibile utilizzare BOOL nonatomici in una situazione che richiede BOOL atomici. Il codice non sarebbe portatile per il sistema operativo Road Light, ma se è possibile sacrificare la protezione futura del proprio codice non anatomico va bene per questo caso d'uso. Sono sicuro che ci sono individui induriti su s.o. ciò solleverebbe la sfida di smontare BOE getter sintetizzati e setter per casi atomici/non anatomici per vedere qual è la differenza. Almeno su ARM.

tuo asporto da questo è probabile che questo

  1. è possibile dichiarare le proprietà BOOL come atomica e non ti costerà un centesimo su tutti HW iOS e MacOS supporta intrinsecamente.
  2. barriere di memoria sono ortogonali atomicità
  3. voi sicuramente non si dovrebbe usare di 4 immobili byte per memorizzare booleani in a meno che non si è in [molto] logica fuzzy. È idiota e sprecona, non vuoi essere un clone di un programmatore Java, che non sa distinguere un float da un doppio, o no?
  4. variabili BOOL (che non ovviamente supportano atomici/nonatomic decoratori non sarebbe atomica su alcune architetture di bus strette obiettivo C sarebbe non essere utilizzato su ogni caso (microcontrollori con o senza qualche [molto] micro OS sono C territorio & assemblaggio suppongo. che in genere non hanno bisogno del bagaglio runtime objc porterebbe)