c++ - GNU C++ 中的原子交换

标签 c++ g++ atomic atomic-swap

我想验证我的理解是否正确。这种事情很棘手,所以我几乎可以肯定我错过了一些东西。我有一个由实时线程和非实时线程组成的程序。我希望非 RT 线程能够交换指向 RT 线程使用的内存的指针。

从文档中,我的理解是这可以在 g++ 中完成:

// global
Data *rt_data;

Data *swap_data(Data *new_data)
{
#ifdef __GNUC__
    // Atomic pointer swap.
    Data *old_d = __sync_lock_test_and_set(&rt_data, new_data);
#else
    // Non-atomic, cross your fingers.                                          
    Data *old_d = rt_data;
    rt_data = new_data;
#endif
    return old_d;
}

这是程序中唯一修改 rt_data 的地方(初始设置除外)。在实时上下文中使用 rt_data 时,会将其复制到本地指针。对于old_d,稍后当确定旧内存未被使用时,将在非RT线程中释放。这个对吗?我在任何地方都需要 volatile 吗?还有其他我应该调用的同步原语吗?

顺便说一句,我在 C++ 中执行此操作,但我对 C 的答案是否不同感兴趣。

提前谢谢。

最佳答案

C/C++写并发代码时一般不要使用volatilevolatile 的语义非常接近你想要的,它很诱人,但最终 volatile 是 not enough .不幸的是 Java/C# volatile != C/C++ volatile。 Herb Sutter 有一个很棒的 article解释困惑的困惑。

你真正想要的是一个内存栅栏。 __sync_lock_test_and_set 为您提供围栏。

当您将 rt_data 指针复制(加载)到本地拷贝时,您还需要一个内存栅栏。

无锁编程很棘手。如果你愿意使用 Gcc 的 c++0x 扩展,那就简单一点:

#include <cstdatomic>

std::atomic<Data*> rt_data;

Data* swap_data( Data* new_data )
{
   Data* old_data = rt_data.exchange(new_data);
   assert( old_data != new_data );
   return old_data;
}

void use_data( )
{
   Data* local = rt_data.load();
   /* ... */
}

关于c++ - GNU C++ 中的原子交换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2478397/

相关文章:

c++ - 什么是 .h.gch 文件?

g++ 3.4.6 中的 C++ 构造函数/复制构造函数问题

linux - 用于调试应用程序的多个实例的源代码位置

c++ - libsodium crypto_sign_open 返回添加一些字符的未签名消息

c++ - Qt QTreeView 添加到模型时不更新

C++ for循环数组赋值。得到垃圾返回

c++ - 每个 memory_order 是什么意思?

c++ - 了解旧 C++ 代码的行为

GCC 4.7,包括 <stdatomic.h>

c++ - 独立的读-修改-写顺序