Функции для выполнения атомарных операций

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

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

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

ОС: Windows, Linux, Solaris и VxWorks


person Jay    schedule 20.02.2010    source источник


Ответы (5)


До С11

В библиотеке 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).

person Jerry Coffin    schedule 20.02.2010
comment
synch_fetch_and* работает довольно хорошо и совместимо со всем, что поддерживает gcc, кроме ARM. +1 - person Tim Post♦; 21.02.2010

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

person bmargulies    schedule 20.02.2010

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

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

person Michael Ekstrand    schedule 20.02.2010

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

person dirkgently    schedule 20.02.2010

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

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

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

person AndiDog    schedule 20.02.2010