2016-07-22 38 views
2

我想以原子方式和非原子方式操纵相同的内存位置。通过联合对原子进行非原子访问

让我们假设我有一个简单类型的工作,就像一个int,尤其是std::atomic<T>::is_lock_free()回报true,那sizeof(T) == sizeof(std::atomic<T>)

我认为,一个reinterpret_cast应该工作:

std::atomic<int> x; 
int& xx = reinterpret_cast<int&>(x); 

N4013解释说,这可能会在编译器混淆基于类型的别名分析,因此是不可靠的。

我的问题是:union怎么办?如果我创建以下内容:

union AtomicInt 
{ 
    int nonatomic; 
    std::atomic<int> atomic; 
}; 

AtomicInt x; 
x.nonatomic = 5; 
x.atomic.compare_exchange_weak(...); 

这是否按预期工作?我能以原子方式和非原子方式操作相同的内存吗?


抢占约代替非原子操作的使用load(std::memory_order_relaxed)建议, 我试过在this answer的建议,一个相关的问题,但它减缓我的代码下降了50%。

+0

是什么让你认为'std :: atomic '在内部与'int'相同? –

+0

如果它无锁且尺寸相同,我很难想象它会有所不同。 – foxcub

+0

我也是,但我一直在这样的事情错了。我敢说,你会得到的最好结果是它看起来工作得很好 - 直到它没有。你永远不会失败,甚至不会注意到它。访问存储的值将以完全不同的方式完成。例如,通过“int”所做的更改可能对另一个CPU上运行的线程不可见。看看你的编译器发出的指令,看看它是否应该工作。充其量,我会说“工作”将是平台依赖的UB。但出于性能方面的原因,您可能需要这样做。 –

回答

0

无锁原子基元用于高度拥塞的并发。如果拥挤程度很高,并且您开始将原子变量用作非原子,那么如果在特定架构intatomic<int>具有相同的布局,您肯定会引入错误甚至

如果您的拥堵率低,但在某些情况下需要特殊排序,则应使用锁定。

+2

我永远不会开始在并行执行过程中使用我的变量作为非原子。我想在原子执行之前的串行执行期间将它们用作非原子。 – foxcub

+0

那么为什么不只在它之前使用另一个(非原子)变量,并在稍后将它分配给一个原子? – Dutow

+1

我不想复制(和内存)的开销。 – foxcub