Atomic types
Содержание |
Синтаксис
_Atomic
(
type-name
)
|
(1) | (начиная с C11) | |||||||
_Atomic
type-name
|
(2) | (начиная с C11) | |||||||
const
,
volatile
и
restrict
, однако, в отличие от других квалификаторов, атомарная версия
type-name
может иметь другой размер, выравнивание и представление объекта.
| type-name | - | любой тип, кроме массива или функции. Для (1) , type-name также не может быть атомарным или cvr-квалифицированным |
Заголовочный файл <stdatomic.h> определяет множество удобных псевдонимов типов , от atomic_bool до atomic_uintmax_t , которые упрощают использование этого ключевого слова со встроенными и библиотечными типами.
_Atomic const int* p1; // p - указатель на атомарный const int const atomic_int* p2; // то же const _Atomic(int)* p3; // то же
Если макроконстанта __STDC_NO_ATOMICS__ определена компилятором, ключевое слово _Atomic не предоставляется.
Объяснение
Объекты атомарных типов являются единственными объектами, свободными от гонок данных ; то есть они могут быть модифицированы двумя потоками одновременно или модифицированы одним потоком и прочитаны другим.
Каждый атомарный объект имеет свой собственный ассоциированный
порядок модификаций
, который представляет собой полный порядок модификаций, выполненных над этим объектом. Если, с точки зрения некоторого потока, модификация
A
некоторого атомарного
M
happens-before
модификация
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.
Некоторые атомарные операции также являются операциями синхронизации; они могут иметь дополнительную семантику освобождения (release), семантику захвата (acquire) или последовательно-согласованную семантику (sequentially-consistent). См. memory_order .
Встроенные операторы инкремента и декремента и составные присваивания являются атомарными операциями read-modify-write с полным последовательно согласованным упорядочением (как при использовании memory_order_seq_cst ). Если требуются менее строгие семантики синхронизации, вместо них могут использоваться функции стандартной библиотеки .
Атомарные свойства имеют смысл только для lvalue-выражений . Преобразование lvalue-to-rvalue (которое моделирует чтение памяти из атомарной ячейки в регистр процессора) снимает атомарность вместе с другими квалификаторами.
|
Этот раздел не завершён
Причина: требуется дополнительная информация, пересмотреть взаимодействие с memory_order и страницами библиотеки atomic |
Примечания
Доступ к члену атомарной структуры/объединения является неопределенным поведением.
Тип библиотеки sig_atomic_t не обеспечивает межпоточную синхронизацию или упорядочивание памяти, только атомарность.
Типы
volatile
не обеспечивают межпоточную синхронизацию, порядок операций с памятью или атомарность.
Рекомендуется, чтобы реализации обеспечивали, чтобы представление
_Atomic
(
T
)
в C совпадало с представлением
std
::
atomic
<
T
>
в C++ для любого возможного типа
T
. Механизмы, используемые для обеспечения атомарности и порядка памяти, должны быть совместимы.
Ключевые слова
Пример
#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); }
Возможный вывод:
The atomic counter is 10000 The non-atomic counter is 8644
Ссылки
- Стандарт C23 (ISO/IEC 9899:2024):
-
- 6.7.2.4 Спецификаторы атомарных типов (стр.: TBD)
-
- 7.17 Атомарные операции <stdatomic.h> (стр.: TBD)
- Стандарт 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++ documentation
для
atomic
|