Ragionamento su modelli di memoria (C ++)

3

Ho letto dei modelli di memoria C ++ e penso di avere una conoscenza dei concetti di base che succedono - prima, sincronizza-e inter-thread succede-prima. Tuttavia, applicarli in alcuni esempi è stato difficile. In particolare, ho pensato alla seguente sequenza di operazioni quando sono state ripetute:

Thread 1
1. Atomic store of X in A (seq cst).
2. Write X to B.
3. Atomic store of X in C (seq cst).

Thread 2
4. Atomic load of C.
5. Read of B.
6. Atomic load of A.

Ora so che dopo il 4 Thread 2 devo vedere la scrittura fatta da Thread 1 in 2, ma cosa succede se il Thread 1 sta girando e dopo che 3 sta impostando A, poi B e poi da C a Y? Penso che Thread 2 possa vedere C impostato su X e B su Y perché Thread 1 può avere impostato A e B su Y ma non ha ancora impostato C a Y. Questo è chiaro, ma se Thread 2 controlla A e trova che è impostato su X, significa che Thread 2 deve anche vedere B impostato su X? Ho scritto del codice per far girare Thread 1 e Thread 2 e ho scoperto che se Thread 2 vede lo stesso valore per A e C, anche B ha lo stesso valore. So comunque che questo non lo dimostra, che è la ragione di questa domanda.

Penso che la cosa fondamentale sia se l'atomic store in 1 implica qualcosa sul negozio in 2? Se 2 è stato fatto prima di 1 allora lo fa, ma non è questo il caso. Se il risultato di 2 è visto dal Thread 2 prima che veda i risultati di 1 e 3, il Thread 2 vedrebbe A e C impostati su X ma B su Y. È possibile? Come sarebbe descritto in base ai concetti di cui sopra. Infine, sono entrati in gioco altri fattori che potrebbero significare che il programma che ho scritto funziona (su x86)?

    
posta Elm 01.10.2016 - 16:02
fonte

1 risposta

2

Analizziamo la tua ipotesi iniziale:

I know that following 4 Thread 2 must see the write made by Thread 1 in 2

Il primo esempio potrebbe funzionare:

      Thread 1                    Thread 2 

  1. atomic store in A:  X
  2. write in B : X
  3. atomic store in C : X
                              4. atomic load of C  -> X
                              5. read B  -> X
                              6. atomic load of A -> X

Il secondo esempio non sarà:

      Thread 1                    Thread 2 
                        initially A,B and C hold Z

  1. atomic store in A:  X
                              4. atomic load of C  -> Z
  2. write in B : X           5. read B  -> ?? (UB: can b Z, can be X, can be a mix or anything else  
  3. atomic store in C : X
                              6. atomic load of A -> X

In questo esempio si verificano due problemi, in primo luogo il caricamento di C può verificarsi prima della scrittura, causando il recupero del valore precedente. Secondo, e peggio, l'accesso di B non è garantito per essere atomico e non protetto contro una gara: quindi potresti provare UB.

Ora alla tua domanda:

what happens if Thread 1 is spinning and after 3 is setting A then B and then C to Y ?

Diamo un'occhiata a uno scenario potenziale:

      Thread 1                    Thread 2 

  1. atomic store in A:  X
  2. write in B : X
  3. atomic store in C : X
                              4. atomic load of C  -> X
  n. atomic store in A: Y     5. read B  -> X
  n+1. write in B: Y          6. atomic load of A -> Y
  n+2. atomic sore in C : Y

Ancora una volta, potresti non avere ciò che ti aspettavi. Qui ottengo Y in A ma potrei avere X. Potrei ottenere X in B, ma potrei anche avere Y o anche un valore inaspettato in caso di una gara.

Conclusione

La relazione prima di all'interno di un singolo thread è diretta e segue il flusso di controllo predeterminato / prevedibile.

Non appena hai una sincronizzazione tra due thread (qui la lettura di atomic), il "inter-thread happen-before" non è predeterminato. Dipende dal momento della sincronizzazione, e deve essere analizzato osservando il relativo accadere, prima di ogni discussione, senza dimenticare che immediatamente dopo altre cose potrebbe ancora cambiare.

Infine, evita variabili condivise non atomiche, a meno che non le proteggi con un lucchetto per impedire la corsa dei dati.

    
risposta data 01.10.2016 - 16:41
fonte

Leggi altre domande sui tag