c++ c++11 memory-model

c++ - ¿En qué se diferencian memory_order_seq_cst y memory_order_acq_rel?



c++11 memory-model (2)

Todavía use la definición y el ejemplo de http://en.cppreference.com/w/cpp/atomic/memory_order . Pero reemplace memory_order_seq_cst con memory_order_release en la tienda y memory_order_acquire en la carga.

El pedido de Release-Acquire garantiza todo lo que sucedió, antes de que una tienda en un hilo se convierta en un efecto secundario visible en el hilo que hizo una carga. Pero en nuestro ejemplo, nada sucede antes de almacenar tanto en thread0 como en thread1.

x.store(true, std::memory_order_release); // thread0 y.store(true, std::memory_order_release); // thread1

Además, sin memory_order_seq_cst, el orden secuencial de thread2 y thread3 no está garantizado. Puedes imaginar que se convierten en:

if (y.load(std::memory_order_acquire)) { ++z; } // thread2, load y first while (!x.load(std::memory_order_acquire)); // and then, load x if (x.load(std::memory_order_acquire)) { ++z; } // thread3, load x first while (!y.load(std::memory_order_acquire)); // and then, load y

Por lo tanto, si thread2 y thread3 se ejecutan antes de thread0 y thread1, eso significa que tanto x como y permanecen falsos, por lo tanto, ++ z nunca se toca, z permanece 0 y el aserto se dispara.

Sin embargo, si memory_order_seq_cst ingresa a la imagen, establece un único orden de modificación total de todas las operaciones atómicas que están etiquetadas. Por lo tanto, en thread2, x.load entonces y.load; en thread3, y.load entonces x.load son cosas seguras.

Las tiendas son operaciones de liberación y las cargas son operaciones de adquisición para ambas. Sé que memory_order_seq_cst tiene la intención de imponer un pedido total adicional para todas las operaciones, pero no puedo crear un ejemplo donde no sea el caso si todos los memory_order_seq_cst son reemplazados por memory_order_acq_rel .

¿Echo de menos algo, o la diferencia es solo un efecto de documentación, es decir, uno debería usar memory_order_seq_cst si uno no quiere jugar con un modelo más relajado y usa memory_order_acq_rel cuando restringe el modelo relajado?


http://en.cppreference.com/w/cpp/atomic/memory_order tiene un buen ejemplo en la parte inferior que solo funciona con memory_order_seq_cst . Esencialmente memory_order_acq_rel proporciona memory_order_acq_rel lectura y escritura relativos a la variable atómica, mientras que memory_order_seq_cst proporciona memory_order_seq_cst lectura y escritura a nivel global. Es decir, las operaciones coherentes secuenciales son visibles en el mismo orden en todos los subprocesos.

El ejemplo se reduce a esto:

bool x= false; bool y= false; int z= 0; a() { x= true; } b() { y= true; } c() { while (!x); if (y) z++; } d() { while (!y); if (x) z++; } // kick off a, b, c, d, join all threads assert(z!=0);

Las operaciones en z están protegidas por dos variables atómicas, no una, por lo que no puede usar la semántica de liberación adquirida para imponer que z siempre se incrementa.