Атомные типы
Синтаксис
_Atomic ( имя_типа ) |
(1) | (с C11) |
_Atomic имя_типа |
(2) | (с C11) |
| имя_типа | - | любой тип, кроме массива или функции. Для (1), имя_типа также не может быть атомным или иметь квалификаторы cvr |
Заголовок <stdatomic.h> определяет 37 псевдонимов типов, от atomic_bool до atomic_uintmax_t, которые упрощают использование этого ключевого слова с встроенными и библиотечными типами.
_Atomic const int * p1; // p is a pointer to an atomic const int const atomic_int * p2; // same const _Atomic(int) * p3; // same
Если макроконстанта __STDC_NO_ATOMICS__ определена компилятором, ключевое слово _Atomic не предоставляется.
Объяснение
Объекты атомных типов — единственные объекты, свободные от гонок данных; то есть они могут быть изменены двумя потоками одновременно или изменены одним и прочитаны другим.
Каждый атомный объект имеет свой собственный связанный порядок модификаций, который представляет собой полное упорядочение модификаций, внесённых в этот объект. Если с точки зрения какого-либо потока модификация A некоторого атомного M предшествует модификации B того же атомного M, то в порядке модификаций M A происходит до B.
Обратите внимание, что, хотя каждый атомный объект имеет свой собственный порядок модификаций, нет единого полного порядка; различные потоки могут наблюдать модификации различных атомных объектов в различных порядках.
Гарантируется четыре согласованности для всех атомных операций:
- Согласованность запись-запись: Если операция A, изменяющая атомный объект M, предшествует операции B, изменяющей M, то A появляется раньше B в порядке модификаций M.
- Согласованность чтение-чтение: Если вычисление значения A атомного объекта M происходит до вычисления значения B объекта M, и A берёт своё значение из побочного эффекта X на M, то вычисленное значение B — это либо значение, сохранённое X, либо значение, сохранённое побочным эффектом Y на M, где Y появляется позже X в порядке модификаций M.
- Согласованность чтение-запись: Если вычисление значения A атомного объекта M предшествует операции B на M, то A берёт своё значение из побочного эффекта X на M, где X появляется перед B в порядке модификаций M.
- Согласованность запись-чтение: Если побочный эффект X на атомном объекте M предшествует вычислению значения B объекта M, то вычисление B берёт своё значение из X или из побочного эффекта Y, который появляется после X в порядке модификаций M.
Некоторые атомные операции также являются синхронизирующими операциями; они могут иметь дополнительную семантику освобождения, приобретения или последовательно согласованной семантики. См. memory_order.
Встроенные операторы инкремента и декремента и составные присваивания — это атомные операции чтения-модификации-записи с полным порядком последовательно согласованной (как если бы использовали memory_order_seq_cst). Если требуется менее строгая семантика синхронизации, вместо этого можно использовать функции стандартной библиотеки.
Атомные свойства имеют смысл только для lvalue выражений. Преобразование lvalue в rvalue (которое моделирует чтение из атомной ячейки в регистр процессора) удаляет атомность вместе с другими квалификаторами.
Примечания
Обращение к члену атомной структуры/объединения — неопределённое поведение.
Библиотечный тип sig_atomic_t не обеспечивает межпоточную синхронизацию или порядок памяти, только атомность.
Типы volatile не обеспечивают межпоточную синхронизацию, порядок памяти или атомность.
Рекомендуется, чтобы реализации гарантировали, что представление _Atomic(T) в C такое же, как у std::atomic<T> в C++, для каждого возможного типа T. Механизмы, используемые для обеспечения атомности и порядка памяти, должны быть совместимы.
Ключевые слова
Пример
#include <stdio.h>
#include <threads.h>
#include <stdatomic.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);
}Возможный вывод:
The atomic counter is 10000 The non-atomic counter is 8644
Ссылки
- Стандарт C17 (ISO/IEC 9899:2018):
- 6.7.2.4 Атомные спецификаторы типа (стр: 87)
- 7.17 Атомные типы <stdatomic.h> (стр: 200-209)
- Стандарт C11 (ISO/IEC 9899:2011):
- 6.7.2.4 Атомные спецификаторы типа (стр: 121)
- 7.17 Атомные типы <stdatomic.h> (стр: 273-286)
См. также
Документация по C для thread (Concurrency support library) |
|
Документация по C++ для atomic |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/language/atomic