7

Ho bisogno di aiuto per capire la sincronizzazione con la relazione. Più lo sto leggendo cercando di capire un esempio, più sento di non capire nulla. A volte sento che è così, ce l'ho, ma dopo aver visto un altro esempio mi confondo ancora. Per favore aiutami a farlo bene.sincronizza-con, accade-prima relazione e semantica acquisizione-rilascio

Si dice che un'operazione A si sincronizzi con un'operazione B se A è un negozio ad una variabile atomica m, con semantica di rilascio, B è un carico dalla stessa variabile m, con semantica acquisita, e B legge il valore memorizzate da A. si dice anche che un'operazione un accade-prima di un'operazione B se

  • a viene eseguita sullo stesso thread come B, e a è prima B in ordine di programma, o
  • a sincronizza -con B, o
  • Un evento-prima di qualche altra operazione C, e C succede-prima di B

OK. Se guardiamo questo esempio

thread0 esegue | thread1 esegue


store x (rilascio) | caricare x (acquisire)

memorizza in x qui sincronizzare con carico da x? Se abbiamo sincronizzato -con relazione qui, quindi memorizza in x succede prima di caricare da x, quindi tutto ciò che è sequenziato prima di memorizzare in x nel thread 0 accade-prima di caricare da x nel thread 1. Significa che qui c'è un ordine forzato. È giusto? Ma in questo caso non capisco cosa significa "e B legge il valore memorizzato da A" parte della definizione significa? Se il thread 1 è più veloce, il thread 0 potrebbe leggere il vecchio valore. Quindi qual è la relazione qui e c'è qualche relazione? Se non c'è, come posso fornire quella relazione?

Grazie in anticipo.

+0

un grande articolo è qui http://preshing.com/20130823/the-synchronizes-with-relation/ – camino

risposta

4

Non posso dire di conoscere bene la terminologia, ma è così che penso che vada. Utilizzerò le definizioni .NET per i termini: "Un'operazione ha acquisito la semantica se altri processori vedranno sempre il suo effetto prima di qualsiasi effetto dell'operazione successiva. Un'operazione ha semantica di rilascio se altri processori vedranno l'effetto di ogni operazione precedente prima dell'effetto del "

Non esiste un ordine forzato tra il negozio e il carico nell'esempio. O uno può essere eseguito per primo. A si sincronizza con B quando l'operazione di memorizzazione viene eseguita prima del caricamento. Quando ciò accade, tutte le operazioni precedenti allo store (release) sono garantite per essere eseguite prima che le operazioni dopo il caricamento (acquisizione) vengano eseguite.

Tuttavia, l'operazione di caricamento può essere eseguita prima del negozio. In tal caso A non si sincronizza con B (poiché la condizione "e B legge il valore memorizzato da A" non è vera) e quindi le operazioni dopo il caricamento possono essere eseguite prima delle operazioni che precedono il negozio. L'ordine è vago.

La semantica di rilascio garantisce che per un determinato valore di x si saprà che le operazioni precedenti al negozio verranno eseguite prima di poter caricare lo stesso valore memorizzato nel secondo thread (e prima di poter eseguire le operazioni seguendo il carico).

Supponiamo che contano e bandiera vengono inizializzati a zero e entrambi i fili vengono eseguite in parallelo:

thread0: 
st   count, 1 (A) 
st.release flag, 1 (B) 

thread1: 
ld.acquire flag  (C) 
ld   count  (D) 

Sappiamo che accade-prima B e C accade-prima D, perché il loro ordine costretto dalla il rilascio e acquisire semantica. L'ordine di B e C non è definito. Viene definito solo quando B si sincronizza con C e quindi sappiamo che A accade prima di D (come succede A - prima che B accada - prima che C accada - prima di D).

In thread1 il conteggio è sempre 1 se flag è 1. Se flag è 0 il conteggio può essere 0 o 1. È possibile testare il flag per determinare se l'altro thread ha impostato il valore sul conteggio.

Senza acquisire e rilasciare semantica, i carichi e i negozi possono essere riordinati e sia il flag che il conteggio potrebbero essere 0 o 1 senza dipendenza l'uno dall'altro.

Se vogliamo garantire che B accada - prima di C, possiamo usare semafori o qualche altro meccanismo di attesa e segnale. Nell'esempio precedente potremmo far rispettare l'ordine in attesa che il flag venga impostato.

thread1: 
ld.acquire flag  (C) 
repeat C while flag == 0 
ld   count  (D)