Namespaces
Variants

Atomic types

From cppreference.net

Contenidos

Sintaxis

_Atomic ( type-name ) (1) (desde C11)
_Atomic type-name (2) (desde C11)
1) Utilizar como especificador de tipo; esto designa un nuevo tipo atómico
2) Úsese como calificador de tipo; esto designa la versión atómica de type-name . En este rol, puede combinarse con const , volatile , y restrict , aunque a diferencia de otros calificadores, la versión atómica de type-name puede tener un tamaño, alineación y representación de objeto diferentes.
type-name - cualquier tipo excepto array o función. Para (1) , type-name tampoco puede ser atomic o calificado cvr

El encabezado <stdatomic.h> define muchos alias de tipos convenientes , desde atomic_bool hasta atomic_uintmax_t , que simplifican el uso de esta palabra clave con tipos incorporados y de biblioteca.

_Atomic const int* p1;  // p es un puntero a un atomic const int
const atomic_int* p2;   // igual
const _Atomic(int)* p3; // igual

Si la macro constante __STDC_NO_ATOMICS__ está definida por el compilador, la palabra clave _Atomic no está disponible.

Explicación

Los objetos de tipos atómicos son los únicos objetos que están libres de carreras de datos ; es decir, pueden ser modificados por dos hilos concurrentemente o modificados por uno y leídos por otro.

Cada objeto atómico tiene su propio orden de modificación asociado, que es un orden total de las modificaciones realizadas a ese objeto. Si, desde el punto de vista de algún hilo, la modificación A de algún atómico M sucede-antes que la modificación B del mismo atómico M , entonces en el orden de modificación de M , A ocurre antes que B .

Tenga en cuenta que aunque cada objeto atómico tiene su propio orden de modificación, no existe un orden total único; diferentes hilos pueden observar modificaciones a diferentes objetos atómicos en órdenes diferentes.

Existen cuatro tipos de coherencia que están garantizados para todas las operaciones atómicas:

  1. coherencia escritura-escritura : Si una operación A que modifica un objeto atómico M sucede-antes que una operación B que modifica M , entonces A aparece antes que B en el orden de modificación de M .
  2. coherencia lectura-lectura : Si una computación de valor A de un objeto atómico M sucede antes que una computación de valor B de M , y A toma su valor de un efecto secundario X sobre M , entonces el valor computado por B es o bien el valor almacenado por X o es el valor almacenado por un efecto secundario Y sobre M , donde Y aparece después de X en el orden de modificación de M .
  3. coherencia lectura-escritura : Si una computación de valor A de un objeto atómico M sucede-antes que una operación B sobre M , entonces A toma su valor de un efecto secundario X sobre M , donde X aparece antes que B en el orden de modificación de M .
  4. coherencia escritura-lectura : Si un efecto secundario X sobre un objeto atómico M sucede-antes que una computación de valor B de M , entonces la evaluación B toma su valor de X o de un efecto secundario Y que aparece después de X en el orden de modificación de M .

Algunas operaciones atómicas también son operaciones de sincronización; pueden tener semánticas de liberación adicionales, semánticas de adquisición o semánticas de consistencia secuencial. Consulte memory_order .

Operadores integrados de incremento y decremento y asignación compuesta son operaciones atómicas de lectura-modificación-escritura con ordenación secuencialmente consistente total (como si se usara memory_order_seq_cst ). Si se desean semánticas de sincronización menos estrictas, pueden usarse en su lugar las funciones de la biblioteca estándar .

Las propiedades atómicas solo son significativas para expresiones lvalue . La conversión de lvalue a rvalue (que modela una lectura de memoria desde una ubicación atómica a un registro de CPU) elimina la atomicidad junto con otros calificadores.

Notas

Acceder a un miembro de una estructura/unión atómica es un comportamiento indefinido.

El tipo de biblioteca sig_atomic_t no proporciona sincronización entre hilos ni ordenamiento de memoria, solo atomicidad.

Los tipos volatile no proporcionan sincronización entre hilos, ordenamiento de memoria ni atomicidad.

Se recomienda a las implementaciones garantizar que la representación de _Atomic ( T ) en C sea la misma que la de std :: atomic < T > en C++ para todo tipo posible T . Los mecanismos utilizados para garantizar atomicidad y ordenamiento de memoria deben ser compatibles.

Palabras clave

_Atomic

Ejemplo

#include <stdatomic.h>
#include <stdio.h>
#include <threads.h>
atomic_int acnt;
int cnt;
int f(void* thr_data)
{
    for (int n = 0; n < 1000; ++n)
    {
        ++cnt;
        ++acnt;
        // for this example, relaxed memory order is sufficient, e.g.
        // atomic_fetch_add_explicit(&acnt, 1, memory_order_relaxed);
    }
    return 0;
}
int main(void)
{
    thrd_t thr[10];
    for (int n = 0; n < 10; ++n)
        thrd_create(&thr[n], f, NULL);
    for (int n = 0; n < 10; ++n)
        thrd_join(thr[n], NULL);
    printf("The atomic counter is %u\n", acnt);
    printf("The non-atomic counter is %u\n", cnt);
}

Salida posible:

The atomic counter is 10000
The non-atomic counter is 8644

Referencias

  • Estándar C23 (ISO/IEC 9899:2024):
  • 6.7.2.4 Especificadores de tipo atómico (p: TBD)
  • 7.17 Atomics <stdatomic.h> (p: TBD)
  • Estándar C17 (ISO/IEC 9899:2018):
  • 6.7.2.4 Especificadores de tipo atómico (p: 87)
  • 7.17 Atomics <stdatomic.h> (p: 200-209)
  • Estándar C11 (ISO/IEC 9899:2011):
  • 6.7.2.4 Especificadores de tipo atómico (p: 121)
  • 7.17 Atomics <stdatomic.h> (p: 273-286)

Véase también

Biblioteca de soporte para concurrencia