Sono l’assegnazione di riferimento e la lettura delle operazioni atomiche?

Ho trovato diverse domande su questo stesso argomento ma relative a variabili generali (valore e tipi di riferimento) La risposta accettata da questa domanda dice:

La partizione I, sezione 12.6.6 della specifica CLI afferma: “Una CLI conforms garantisce che l’accesso in lettura e scrittura a posizioni di memoria correttamente allineate non più grandi della dimensione nativa della parola sia atomico quando tutti gli accessi in scrittura a una posizione sono della stessa dimensione “.

Le variabili di riferimento (cioè le classi) sono puntatori, uguali alla dimensione della parola nativa, ma ho un paio di dubbi:

I riferimenti sono garantiti in posizioni di memoria correttamente allineate?

Non capisco l’ultima parte. Cosa significa questo? “… quando tutti gli accessi in scrittura a una posizione sono della stessa dimensione.”

In breve, obj2 è garantito essere valido in ogni iterazione del ciclo nel seguente codice?

class MyClass { private OtherClass m_Object; void Thread1() { while(true) { OtherClass obj1 = new OtherClass(); m_Object = obj1; } } void Thread2() { while (true) { OtherClass obj2 = m_Object; // Is obj2 guaranteed to be valid? obj2.Check(); } } } 

Sì, è garantito che tutto sia allineato correttamente, a meno che non si decida deliberatamente di non allineare le cose, il che significa che l’assegnazione / lettura di riferimento è garantita per essere atomica.

La sezione 12.6.6 delle specifiche CLI continua dicendo questo:

A meno che non si utilizzi il controllo esplicito del layout (vedi Partizione II (Controlling Instance Layout)) per modificare il comportamento predefinito, gli elementi di dati non più grandi della dimensione naturale della parola (la dimensione di un native int ) devono essere allineati correttamente. I riferimenti agli oggetti devono essere trattati come se fossero memorizzati nella dimensione della parola nativa.

Ci sono anche ulteriori dettagli sull’allineamento ecc. Nella sezione 12.6.2 della specifica.

Si noti che nel codice di esempio, la lettura nel thread 2 è garantita per essere atomica, ma non è garantito vedere effettivamente le modifiche apportate da thread 1: senza imporre barriere di memoria o volatilità ogni thread può utilizzare la propria “vista” di m_Object campo senza mai vedere le modifiche apportate da altri thread.

Quindi, ad esempio, il thread 1 potrebbe creare scritture (atomiche) nella propria vista di m_Object , ma i dati vengono sempre effettivamente trattenuti in un registro o nella cache della CPU e non vengono mai inviati alla memoria principale. Allo stesso modo, il thread 2 potrebbe anche essere la lettura (atomica) di m_Object , ma in realtà la lettura da un registro o dalla cache della CPU piuttosto che dalla memoria principale.