A Small Spin Lock

本文介绍了一个名为SmallSpinLock的自旋锁类的实现细节。该自旋锁使用了原子操作和内存屏障来确保多线程环境下的数据一致性,并提供了一种简单有效的等待策略以减少CPU资源浪费。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <ctime>
#include <cstdlib>

class SmallSpinLock
{
    class Sleeper
    {
    public:
        Sleeper () : _spinCount (0)
        {

        }

        void wait()
        {
            if (_spinCount < kMaxActiveSpin) {
                ++_spinCount;
                asm volatile ("pause");
            }
            else {
                /*
                * Always sleep 0.2ms, assuming this will make the kernel put
                * us down for whatever its minimum timer resolution is (in
                * linux this varies by kernel version from 1ms to 10ms).
                */
                struct timespec ts = { 0, 200000 };
                nanosleep (&ts, NULL);
            }
        }

    private:
        Sleeper (const Sleeper&);
        Sleeper& operator= (const Sleeper&);

    private:
        uint32_t _spinCount;
        static const uint32_t kMaxActiveSpin = 8000;
    };

private:
    enum { FREE = 0, LOCKED = 1 };
    uint8_t _lock;

    /*
    * Atomically move _lock from "compare" to "newval". Return boolean
    * success. Do not play on or around.
    *
    * 拿comapre变量的值同_lock变量比较是否相等,如果相等则把newval的值赋给_lock,
    * 然后zf标志会被置位,并通过setz设置结果out。即当我们想获得锁的时候这样用:cas (0,1); 返回true表示成功。
    */
    bool cas (uint8_t compare, uint8_t newVal)
    {
        bool out;
        asm volatile ("lock; cmpxchgb %2, (%3);"
                "setz %0;"
                : "=r" (out)
                : "a" (compare), // cmpxchgb constrains this to be in %al
                "q" (newVal),    // Needs to be byte-accessible
                "r" (&_lock)
                : "memory", "flags");
        return out;
    }

    SmallSpinLock (const SmallSpinLock&);
    SmallSpinLock& operator= (const SmallSpinLock&);

public:
    SmallSpinLock ()
    {
        _lock = FREE;
    }

    ~SmallSpinLock ()
    {

    }

    bool try_lock ()
    {
        return cas (FREE, LOCKED);
    }

    void lock ()
    {
        Sleeper sleeper;
        do {
            while (_lock != FREE) {
                asm volatile ("" : : : "memory");
                sleeper.wait ();
            }
        } while (!try_lock ());
        assert (_lock == LOCKED);
    }

    void unlock ()
    {
        assert (_lock == LOCKED);
        asm volatile("" : : : "memory");
        _lock = FREE; // release barrier on x86
    }
};


注:

barrier内存栅栏 
#define barrier()  __asm__ __volatile__("": : :"memory")
 
1)__asm__用于指示编译器在此插入汇编语句
2)__volatile__用于告诉编译器,严禁将此处的汇编语句与其它的语句重组合优化。即:原原本本按原来的样子处理这这里的汇编。
3)memory强制gcc编译器假设RAM所有内存单元均被汇编指令修改,这样cpu中的registers和cache中已缓存的内存单元中的数据将作废。cpu将不得不在需要的时候重新读取内存中的数据。这就阻止了cpu又将registers,cache中的数据用于去优化指令,而避免去访问内存。
4)"":::表示这是个空指令。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值