InterlockedCompareExchange - 具体的对齐要求是什么以及如何实施?

时间:2016-02-12 16:51:12

标签: c++ windows visual-studio memory-alignment lock-free

我无法理解MSDN文档对Interlocked Variable Access系列函数的影响。 我使用InterlockedExchange进行设置,使用InterlockedCompareExchange来获取多个线程使用的成员变量。

该成员位于一个1字节的压缩类中:

#pragma pack(1)
class MyClass {
    char _;
    long m_MyMember;
    // ...
}

所以成员是由

设置的
InterlockedExchange(&m_MyMember, 1);

并通过

获得
long value = InterlockedCompareExchange(&m_MyMember, 0, 0);

InterlockedExchange文档未以任何方式引用对齐(Strg+F "align"),但InterlockedCompareExchange会:

  

此函数的参数必须在32位边界上对齐;否则,该函数将在多处理器x86系统和任何非x86系统上表现不可预测。

但是,据我所知,参数都是堆栈变量,因为可以重写上面的调用

long *ptr  = &m_MyMember;
long zero  = 0;
long value = InterlockedCompareExchange(ptr, zero, zero);

因此我们阻止了本地自动存储类变量。无论 m_MyMember 所在的类都存在,所有完全4字节对齐。 当然,我认为这是错误的,这意味着 ptr 后面的地址必须在4字节边界上对齐。

所以我的问题是:

  1. InterlockedExchange是否真的与对齐无关,还是在文档中发布了?
  2. 你能否确认不是字面上的参数,但long *后面的地址必须是4字节对齐(我不能假设其他参数如何不能4字节对齐,因为它们是堆栈变量)?
  3. 如果2的答案是:如何解决这个问题?更改周围类的对齐不是一个选项,c ++ 11 atomic或boost也不是(所有这些都是由于公司限制以及msvc10到msvc14所需的可编译性)。
  4. 我考虑过声明 m_MyMember volatile并使用关键部分来访问它。虽然我希望更好地正确声明 m_MyMember 以根据需要对齐,因为那些互锁变量访问函数都在给定的代码库周围,我不想为每个变量添加额外的伴随CS

1 个答案:

答案 0 :(得分:1)

限制不是微软的,而是硬件。为了原子地改变东西,它必须对齐(指针)。

对于临界区的成员或STD :: atomic

也是如此

如果没有重新对齐类,如果可以使用interlock变量来保证与类的4字节对齐,那么这应该可以正常工作