更新:是否有一个线程安全的、无锁的、在C或C++中可用的所有Linux发行版增量函数上可用的?
发布于 2009-11-08 01:02:12
GLib具有这样的功能。你可以去看看http://library.gnome.org/devel/glib/stable/glib-Atomic-Operations.html
具体来说,听起来您想要g_atomic_int_inc()
发布于 2021-11-23 16:04:22
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位x86与int64_t和double的alignof(T) < std::atomic_ref<T>::required_alignment)。
请注意,“尽管存在引用对象的任何atomic_ref实例,但必须通过这些atomic_ref实例独占地访问该对象。”
参见论哥德波特如何编译。
// 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 10C
您也可以使用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 std::atomic_ref,没有C等价物。如果您不介意使用GNU扩展,您可以使用C++ atomic和atomic_ref在其之上实现的内置函数,比如内建:__atomic_fetch_add( &i, 1, __ATOMIC_ACQ_REL)。
其他非Linux系统的编译器也有自己的内置程序,例如MSVC和_InterlockedAdd。
它可能正好可以将atomic_int * (又名_Atomic int*)指向int的地址,但这是严格地对未定义的行为进行别名。
发布于 2009-11-08 00:54:51
我认为这些都是GNU扩展和处理器特定的,但是请看一下GNU C原子构建器。
我认为还有一些原子“库”可以使用内联程序集等来提供这样的特性。
https://stackoverflow.com/questions/1694963
复制相似问题