在一个多线程的C++应用程序中,我有两个指针指向一个大的图形对象。
我尝试每5分钟交换它们。哪种方式是安全的并具有最佳性能?
使用C++11的atomic<>
是一个不错的选择。
在一个多线程的C++应用程序中,我有两个指针指向一个大的图形对象。
我尝试每5分钟交换它们。哪种方式是安全的并具有最佳性能?
使用C++11的atomic<>
是一个不错的选择。
交换需要原子操作吗?也就是说,在交换时,您是否需要保证另一个线程不能观察到它们在交换时具有相同的值?
如果您不需要保证交换是原子的,则只需使用两个std::atomic<T *>
对象,并使用临时变量进行交换:
T* tmp = p1;
p1 = p2.load();
p2 = tmp;
struct TwoPointers { T* p1; T* p2; }
std::atomic<TwoPointers> p;
auto old = p.load();
p = { old.p2, old.p1 };
auto old = p.load();
while (!p.compare_exchange_strong(old, { old.p2, old.p1 }))
{ };
compare_exchange_strong
比单个原子存储略慢,但如果每五分钟只发生一次,那么你不会注意到差异。TwoPointers
解决方案也意味着两个指针共享一个缓存行,但如果除了每五分钟的交换之外它们是只读的,那就不是问题。
std::atomic<>
中并调用compare_exchange
函数,例如:http://en.cppreference.com/w/cpp/atomic/atomic/compare_exchange - Nimstd::atomic_int the_flipper;
并将其从 0 翻转到 1,然后再翻转回来:代码可以获取ptr[the_flipper]
或ptr[the_flipper^1]
- 当the_flipper
更改时会解析为不同的指针。然而,我很难想象什么情况下指针短暂相同会有影响(由于竞争条件,无论如何进行原子交换,任何同时读取两个指针的人都可能看到相同的结果),因此像 axiac 建议的那样使用两个std::atomic_uintptr_t
和一个临时变量可能完全可以胜任。 - Tony Delroy