这个快速原子锁实现可以工作吗?
我有一个大型数据结构,它使用条带化来减少锁争用。现在我正在使用系统锁,但99.99%的时间,锁是没有争议的,而且,持有锁的时间非常少。然而,在持有锁的同时,会执行几个不同的内存操作。实际上,与访问数据结构的总时间相比,获取和释放锁所花费的时间非常重要。
所以我考虑用以下非常简单的锁替换操作系统锁。此处仅显示尝试和解锁,因为 99.99% 的情况下 FastTryLock() 都会成功。这里的“pLock”变量表示条带结构中的细粒度锁。
我已经编写了以下实现,它看起来工作正常,但如果它是正确的还是不正确的,我将不胜感激。
bool FastTryLock(DWORD *pLock)
{
if(0==AtomicXCHG(pLock,1)) {
MemoryBarrier_LightWeight(); return(true);
}
return(false);
}
void FastUnlock(DWORD *pLock)
{
MemoryBarrier_LightWeight(); *((volatile DWORD*)pLock)=0;
}
在 PC 上,MemoryBarrier_LightWeight() 是无操作,因为 CPU 保证内存写入顺序。
I have a large data structure that is using striping to reduce lock contention. Right now I am using system locks but 99.99% of the time, the lock is uncontested and futhermore, the amount of time holding the lock is quite miniscule. However, several distinct memory operations are performed while the lock is held. It has actually gotten to the point where the time spent aquiring and releasing the locks is significant compared to the overall time accessing the data structure.
So I thinking about replacing the OS lock with the following very simple lock. Only try and unlock are shown here because the 99.99% of the time FastTryLock() is going to succeed. The "pLock" variable here represents a fine granularity lock in the striped structure.
I have written the following implementation which appears to work fine but I would appreciate confirmation if it is correct or incorrect.
bool FastTryLock(DWORD *pLock)
{
if(0==AtomicXCHG(pLock,1)) {
MemoryBarrier_LightWeight(); return(true);
}
return(false);
}
void FastUnlock(DWORD *pLock)
{
MemoryBarrier_LightWeight(); *((volatile DWORD*)pLock)=0;
}
On the PC, MemoryBarrier_LightWeight() is a no-op since the CPU guarantees memory write ordering.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
是的,这是一种称为自旋锁的技术。但请注意,将指针强制转换为 易失性 并不能保证按照标准工作。只需将您的锁变量声明为
volatile
即可。Yes, this is a technique called spin lock. Note, however, that casting pointer to
volatile
is not guaranteed to work according to standard. Just declare your lock variable asvolatile
instead.