InterlockedExchange vs InterlockedCompareExchange自旋锁

use*_*168 2 c++ multithreading atomic

我使用InterlockedExchange编写了一个基本的自旋锁(见下文).但是我已经看到很多实现使用InterlockedCompareExchange.以某种不可预见的方式是不正确的,如果不是,每种方式的专业和缺点是什么(如果确实有的话)?

PS我知道睡眠是昂贵的,我想在我打电话之前尝试计数.

class SpinLock
{
public:

    SpinLock() : m_lock( 0 ) {}
    ~SpinLock(){}

    void Lock()
    {
        while( InterlockedExchange( &m_lock, 1 ) == 1 )
        { 
            Sleep( 0 ); 
        }
    }

    void Unlock()
    {
        InterlockedExchange( &m_lock, 0 );
    }

private:
    volatile unsigned int m_lock;
};
Run Code Online (Sandbox Code Playgroud)

Nik*_*lis 5

首先,InterlockedExchange需要一个LONG.请在我之后重复:a LONG是不一样的int.这似乎是一件小事,但它可能会让你感到悲伤.

现在,详细说明Mats Petersson所说的内容:

您的自旋锁将具有可怕的性能,因为InterlockedExchange循环Lockm_lock无条件地修改变量,导致后台处理器完成大量工作以维持缓存一致性.

更糟糕的是,通过不确保m_lock变量本身位于缓存行上,上述效果被放大并可能影响其他数据,不幸的是,它们与自旋锁的实例共享缓存行.

这些代码只是两个中度微妙的问题.还有其他人.简单的事实是锁定不容易,你不应该实现自定义锁定原语.请不要重新发明轮子.使用操作系统提供给您的工具.它们本身不太可能成为瓶颈.

如果您确实发现性能问题(即,您具有表明性能瓶颈的分析数据),请首先关注算法更改以及改进并行化和减少锁争用.如果问题仍然存在,那么只有在其他地方看.