我无法理解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系统上表现不可预测 .
但是,据我所知, parameters 都是堆栈变量,因为可以重写上面的调用
long *ptr = &m_MyMember;
long zero = 0;
long value = InterlockedCompareExchange(ptr, zero, zero);
所以我们阻止了本地自动存储类变量 . 所有完美的4字节对齐,无论m_MyMember所在的类是什么 . 当然,我认为这是错误的,这意味着ptr后面的地址必须在4字节边界上对齐 .
所以我的问题是:
-
InterlockedExchange真的是对齐不可知的还是文档中的这个?
-
你可以确认不是字面上的参数,但long *后面的地址必须是4字节对齐(我不能假设其他参数如何不能4字节对齐,因为它们是堆栈变量)?
-
如果2的答案是 yes :如何解决?更改周围类的对齐不是一个选项,c 11 atomic或boost都不是(所有这些都是由于公司限制和msvc10到msvc14所需的可编译性) .
我考虑过声明m_MyMember volatile并使用关键部分来访问它 . 虽然我希望更好地正确声明m_MyMember根据需要对齐,因为那些互锁变量访问函数都在给定的代码库周围,我不想为每个变量添加额外的伴随CS .
1 回答
限制不是微软的,而是硬件 . 为了原子地改变东西,它必须对齐(指针) .
对于临界区的成员或STD :: atomic也是如此
如果你没有重新对齐类,如果你可以使用
interlock
变量来保证与类的4字节对齐,那么这应该工作