线程安全,无锁增量功能?

jld*_*ont 1 c c++ linux multithreading lock-free

更新:在C或C++中可用的所有Linux发行版增量函数都有线程安全,无锁且可用吗?

bal*_*ing 10

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;
}
Run Code Online (Sandbox Code Playgroud)

如果有兴趣,可以编译成(在 gcc 上至少进行 -O1 优化):

mov             DWORD PTR [rsp-4], 5
lock inc        DWORD PTR [rsp-4]
Run Code Online (Sandbox Code Playgroud)

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

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

mov             DWORD PTR [rsp-4], 5
lock inc        DWORD PTR [rsp-4]
Run Code Online (Sandbox Code Playgroud)

C

您也可以使用原子类型执行与我在 C11 中的第一个示例中相同的操作。

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

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

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

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

atomic_int *将 an (又名_Atomic int*)指向 an 的地址可能会起作用int,但这是严格别名未定义的行为。


jst*_*ast 7

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

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


Art*_*ius 6

我认为这些是GNU扩展,特定于处理器,但是看看GNU C Atomic Builtins.

我认为还有可用的原子"库",它们使用内联汇编等来提供这样的功能.