关于自旋锁

时间:2013-02-18 09:12:32

标签: c++ locking

我在boost spinlock代码中有一些问题:

class spinlock
{
public:
    spinlock()
        : v_(0)
    {
    }

    bool try_lock()
    {
        long r = InterlockedExchange(&v_, 1);
        _ReadWriteBarrier();        // 1. what this mean            
        return r == 0;
    }

    void lock()
    {
        for (unsigned k = 0; !try_lock(); ++k)
        {
            yield(k);
        }
    }

    void unlock()
    {

        _ReadWriteBarrier();                      
        *const_cast<long volatile*>(&v_) = 0;  
        // 2. Why don't need to use InterlockedExchange(&v_, 0);
    }

private:
    long v_;
};

3 个答案:

答案 0 :(得分:1)

  1. ReadWriteBarrier()是一个“内存屏障”(在本例中是读写操作),是处理器的一条特殊指令,用于确保导致内存操作的所有指令都已完成(load &amp; store操作 - 或者在x86处理器中,任何在任一侧都有内存操作数的opertion)。在这种特殊情况下,为了确保在我们继续之前InterlockedExchange(&amp; v_,1)已经完成。

  2. 因为InterlockedExchange效率较低(与机器中的任何其他核心进行更多交互以确保所有其他处理器内核都“放开”该值 - 这是没有意义的,因为大多数很可能(在正确工作的代码中)我们只有unlock如果我们实际上持有锁,那么没有其他处理器会有比我们正在写的不同的缓存值,并且volatile写入记忆力也一样好。

答案 1 :(得分:0)

存在阻碍内存同步的障碍;无 它们,不同的线程可能会看到内存的修改 不同的订单。

在第二种情况下,InterlockedExchange不是必需的 因为我们对以前的价值不感兴趣的作用 InterlockedExchange无疑是设定价值和回报 以前的值。 (以及v_为什么long,如果可以的话 只取值01,超出我的范围。)

答案 2 :(得分:0)

对变量进行原子访问有三个问题。首先,确保在读取或写入值的过程中没有线程切换;如果发生这种情况,就会被称为“撕裂”;第二个线程可以看到部分写入的值,这通常是荒谬的。其次,确保所有处理器都能看到通过写入进行的更改,或者处理器读取值会看到之前对该值的任何更改;这被称为“缓存一致性”。第三,确保编译器不会在读或写之间移动代码;这被称为“代码运动”。 InterlockedExchange做前两个;虽然MSDN文档相当混乱,_ReadWriteBarrier执行第三个,可能是第二个。