Domanda

Ho due thread, uno per l'aggiornamento di un'int e la lettura di esso.Questo è un valore della statistica in cui l'ordine della legge e scrive è irrilevante.

La mia domanda è, devo sincronizzare l'accesso a questo multi-byte valore comunque?O, detto in altro modo, può parte della scrittura è completo, e interrotta, e quindi la lettura accadere.

Per esempio, pensare a un valore = 0x0000FFFF che viene incrementato il valore di 0x00010000.

C'è un tempo in cui il valore sembra 0x0001FFFF che dovrei essere preoccupato?Certamente il più grande, il tipo, il più possibile qualcosa come questo accada.

Ho sempre sincronizzato questi tipi di accessi, ma era curioso di sapere che cosa la comunità pensa.

È stato utile?

Soluzione

Inizialmente si potrebbe pensare che legge e scrive dei nativi dimensioni della macchina sono atomica, ma ci sono un certo numero di questioni da affrontare tra cui cache di coerenza tra processori/core.Utilizzare le operazioni atomiche come Interbloccate* su Windows e l'equivalente in Linux.C++0x hanno un "atomica" modello per avvolgere questi in una bella e cross-piattaforma di interfaccia.Per ora, se si utilizza una piattaforma di livello di astrazione può fornire queste funzioni. ACE non, vedere il modello di classe ACE_Atomic_Op.

Altri suggerimenti

Il ragazzo, che domande.La risposta è:

Sì, no, hmmm, beh, dipende

Tutto si riduce all'architettura del sistema.Su IA32 un corretto allineamento indirizzo sarà un'operazione atomica.Non allineate scrive potrebbe essere atomica, dipende dalla cache di sistema in uso.Se la memoria si trova all'interno di una singola linea di cache L1, allora è atomica, altrimenti non.La larghezza del bus tra CPU e RAM possono influenzare la natura atomica:un corretto allineamento dei 16bit scrivere su un 8086 era atomica, mentre la stessa operazione di scrittura su un 8088 non perché 8088 aveva solo un bus a 8 bit, mentre il 8086 era a 16 bit del bus.

Inoltre, se si utilizza C/C++ non dimenticate di segnare il valore condiviso volatile, altrimenti l'ottimizzatore ritiene che la variabile non viene aggiornato in uno dei thread.

SE sei di lettura/scrittura di 4 byte valore DWORD allineati in memoria E si sta eseguendo sul I32 architettura, legge e scrive atomici.

Sì, è necessario sincronizzare gli accessi.In C++0x sarà una data razza, e comportamenti indefiniti.Con i thread POSIX è già definito il comportamento.

In pratica, si potrebbe ottenere male i valori, se il tipo di dati è maggiore rispetto a quella nativa dimensione di parola.Inoltre, un altro thread potrebbe non vedere mai il valore scritto a causa di ottimizzazioni, spostando la lettura e/o scrittura.

È necessario sincronizzare, ma su alcune architetture ci sono modi efficaci per farlo.

Migliore è quello di usare le subroutine (magari mascherato dietro le macro), in modo che è possibile in modo condizionale sostituire le implementazioni con la piattaforma di quelli specifici.

Il kernel di Linux ha già un po ' di questo codice.

Su Windows, Interbloccata***Scambio***Aggiungere è garantito per essere atomica.

Per l'eco di ciò che tutti hanno detto di sopra, la lingua pre-C++0x non può garantire nulla sulla memoria condivisa da più thread.Eventuali garanzie, sarebbe fino al compilatore.

Definitivamente NO !Che risposta da parte nostra massima C++ autorità, M.Boost:
Operazioni "ordinarie" le variabili non sono garantiti per essere atomica.

No, non sono (o almeno non si può assumere sono).Detto questo, ci sono alcuni trucchi per fare questo in modo separato, ma di solito non vengono portatile (vedere Di confronto e di swap).

Sono d'accordo con molti e in particolare Jason.Su windows, si sarebbe probabilmente utilizzare InterlockedAdd e i suoi amici.

Oltre alla cache problema di cui sopra...

Se si porta il codice di un processore con un registro di minori dimensioni dimensioni non sarà atomic più.

IMO, problemi di threading sono troppo spinoso per il rischio.

Consente di prendere questo esempio

int x;
x++;
x=x+5;

La prima istruzione è assunto per essere atomica, perché si traduce in un singolo INC assemblea direttiva che prende un singolo ciclo CPU.Tuttavia, la seconda assegnazione richiede diverse operazioni in modo chiaramente non è un'operazione atomica.

Un altro e.g,

x=5;

Di nuovo, è necessario smontare il codice per vedere cosa succede qui.

tc, Penso che il momento in cui si utilizza una costante ( 6) , l'istruzione non essere completato in un ciclo macchina.Prova a vedere il set di istruzioni di x+=6 rispetto a x++

Alcune persone pensano che il c ++è atomica, ma avere un occhio sull'assembly generato.Per esempio con "gcc-S' :

movl    cpt.1586(%rip), %eax
addl    $1, %eax
movl    %eax, cpt.1586(%rip)

Incremento di una int, il compilatore prima caricare in un registro, e memorizza nuovamente nella memoria.Questo non è atomico.

Il solo portatile, utilizzare il sig_atomic_t tipo definito nel segnale.h intestazione per il compilatore.In più C e C++ implementazioni, che è un int.Quindi dichiarare la variabile come "volatile sig_atomic_t."

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top