2

更新:在 C 或 C++ 中可用的所有 Linux 发行版增量功能上是否有线程安全、无锁和可用?

4

4 回答 4

7

2021年答案

C++

自其他答案以来已经过去了 12 年,现在它已成为标准,并且可以使用原子操作库从 C++11 开始执行此操作。

#include <iostream>
#include <atomic>

int main() {
    std::atomic<int> atomic_i{5};
    std::cout << atomic_i.is_lock_free() << std::endl; // 1, which means lock free
    atomic_i++;
    std::cout << atomic_i << std::endl; // 6
    return 0;
}

如果有兴趣,这将编译为(在 gcc 上至少使用 -O1 优化):

mov             DWORD PTR [rsp-4], 5
lock inc        DWORD PTR [rsp-4]

如果您想要一个普通的非原子整数,并且只想在某些时候在原子操作中递增,那么您可以atomic_ref从 C++20 开始使用,前提是确保它充分对齐。(由于历史 ABI 原因,某些系统未对齐某些非原子类型,但需要自然对齐原子才能实际有效/正确地工作。尤其是 32 位 x86int64_tdoublewhere alignof(T) < std::atomic_ref<T>::required_alignment)。

请注意,“虽然存在引用对象的任何 atomic_ref 实例,但必须通过这些 atomic_ref 实例独占访问该对象。” 在 Godbolt 上
查看它是如何编译的。

// This alignment is redundant for int on most mainstream implementations
// but is important for portability or for wider types like int64_t
alignas(std::atomic_ref<int>::required_alignment)  int j = 8;

... // pass the address of j to other threads
{
    std::atomic_ref<int> refj(j);
    refj++; // atomic operation, j is now 9
}
// refj goes out of scope, so it's ok to use j again

 ... // some synchronization so we know other threads are done for now
j++; // non-atomic increment, j is now 10

C

您也可以使用atomic types做与我在 C11 中的第一个示例中相同的操作。

#include <stdatomic.h>
#include <stdio.h>

int main() {
    atomic_int i = 5;
    i++; // atomic operation
    printf("%d\n", i); // 6
    return 0;
}

C++20 没有 C 等效项std::atomic_ref。如果您不介意使用 GNU 扩展,您可以使用 C++ 的内置函数atomicatomic_ref在其上实现,例如GNU C__atomic内置函数:__atomic_fetch_add( &i, 1, __ATOMIC_ACQ_REL).

用于非 Linux 系统的其他编译器有自己的内置函数,例如MSVC_InterlockedAdd.

atomic_int *将 an (aka )指向 an_Atomic int*的地址可能会起作用int,但这是严格混叠未定义的行为。

于 2021-11-23T16:04:22.187 回答
6

我认为这些是 GNU 扩展,并且是特定于处理器的,但请查看GNU C Atomic Builtins

我认为还有可用的原子“库”使用内联汇编等来提供此类功能。

于 2009-11-08T00:54:51.443 回答
6

GLib 具有执行此操作的功能。你可以看看http://library.gnome.org/devel/glib/stable/glib-Atomic-Operations.html

具体来说,听起来你想要 g_atomic_int_inc()

于 2009-11-08T01:02:12.380 回答
4

当前的 C 和 C++ 标准没有定义这样的东西。您的实现很可能有一个。

于 2009-11-08T00:54:44.920 回答