Функции для выполнения атомарных операций - PullRequest
8 голосов
/ 20 февраля 2010

Существуют ли функции для выполнения атомарных операций (например, увеличение / уменьшение целого числа) и т. Д., Поддерживаемые C Runtime library или любыми другими служебными библиотеками?

Если да, то какие все операции можно сделать атомарными с помощью таких функций?

Будет ли выгоднее использовать такие функции, чем обычные примитивы синхронизации, такие как mutex и т. Д.?

ОС: Windows, Linux, Solaris и VxWorks

Ответы [ 5 ]

7 голосов
/ 20 февраля 2010

до C11

В библиотеке C их нет.

В Linux gcc предоставляет некоторые - ищите __sync_fetch_and_add, __sync_fetch_and_sub и так далее.

В случае Windows ищите InterlockedIncrement, InterlockedDecrement``, InterlockedExchange` и т. Д. Если вы используете gcc в Windows, я предполагаю, что он также имеет те же встроенные функции, что и в Linux (хотя я этого не проверял).

На Солярисе это будет зависеть. Предположительно, если вы используете gcc, он, вероятно, (опять же) будет иметь те же встроенные функции, что и в Linux. В противном случае есть плавающие библиотеки, но на самом деле ничего не стандартизировано.

C11

C11 добавил (разумно) полный набор атомарных операций и атомарных типов. Операции включают в себя такие вещи, как atomic_fetch_add и atomic_fetch_sum*_explicit версии того же самого, которые позволяют вам указать необходимую модель заказа, где стандартные по умолчанию всегда используют memory_order_seq_cst). Есть также fence функции, такие как atomic_thread_fence и atomic_signal_fence.

Типы соответствуют каждому из нормальных целочисленных типов - например, atomic_int8_t соответствует int8_t и atomic_uint_least64_t соответствует uint_least64_t. Это typedef имена, определенные в <stdatomic.h>. Чтобы избежать конфликтов с любыми существующими именами, вы можете опустить заголовок; сам компилятор использует имена в пространстве имен разработчика (например, _Atomic_uint_least32_t вместо atomic_uint_least32_t).

1 голос
/ 20 февраля 2010

На всех поддерживаемых платформах вы можете использовать атомарные операции GLib . На платформах, в которых встроены атомарные операции (например, инструкции по сборке), glib будет их использовать. На других платформах он будет использовать мьютексы.

Я думаю, что атомарные операции могут дать вам ускорение, даже если мьютексы реализованы с их использованием. С мьютексом у вас будет как минимум две атомные операции (блокировка и разблокировка) плюс фактическая операция. Если атомная операция доступна, это одна операция.

1 голос
/ 20 февраля 2010

«Выгодно» является ситуативным. Всегда производительность зависит от обстоятельств. Вы можете ожидать, что что-то чудесное произойдет, когда вы отключите мьютекс для чего-то подобного, но вы можете не получить никакой выгоды (если это не так популярно в случае) или ухудшить ситуацию (если вы случайно создадите «спин-блокировку») .

0 голосов
/ 20 февраля 2010

В Windows есть InterlockedExchange и тому подобное. Для Linux вы можете взять атомные макросы glibc - они переносимы (см. i486 atomic.h ). Я не знаю решения для других операционных систем.

Как правило, вы можете использовать инструкцию xchg на x86 для атомарных операций (также работает на двухъядерных процессорах).

Что касается вашего второго вопроса, нет, я не думаю, что использование атомарных операций будет быстрее, чем использование мьютексов. Например, библиотека pthreads уже реализует мьютексы с атомарными операциями, что очень быстро.

0 голосов
/ 20 февраля 2010

Не уверен, что вы подразумеваете под библиотекой времени выполнения C. Собственно язык или стандартная библиотека не предоставляют никаких средств для этого. Вам нужно будет использовать специфическую для ОС библиотеку / API. Кроме того, не обманывайте себя sig_atomic_t - они не такие, как кажется на первый взгляд, и полезны только в контексте обработчиков сигналов.

...