我想验证我的理解是否正确。这种事情很棘手,所以我几乎可以肯定我错过了一些东西。我有一个由实时线程和非实时线程组成的程序。我希望非 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++
写并发代码时一般不要使用volatile
。 volatile
的语义非常接近你想要的,它很诱人,但最终 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/