自旋锁的应用

通常自旋锁分三种: 纯自旋,队列自旋锁和MCS 锁。 MCS 锁也是基于队列自旋锁的。 但最基本的还是纯自旋锁了。 

自旋锁使用场景:


  1. 通常在一些需要短暂等待的情况下被使用。通常用sleep(0)  也可以办到,但sleep无法控制不切换上下文。

  2. 当多线程锁使用。通常系统底层用来同步多个CPU访问。

纯自旋锁实现如下:

class SpinLock
{

public:

    bool IsLock()
    {
    
        return (m_iFlag ==1);
    }
    int Lock()
    {
        while(InterlockedCompareExchange(m_iFlag,1,0) != 0)
        {
             //不成功,表示其他线程已经加锁了
            //  自旋等待

            Sleep(0);
        }
 
        return 0;
    }

     void UnLock()
     {
        m_iFlag=0;
     }

private:

    volatile  int m_iFlag;
};

通过在m_iFlag 变量上自旋等待来实现锁。

在lock 函数里 ,通过sleep(0) 来自旋,但对效率要求较高的时候, sleep(0) 通常不合适,改进如下:

 int lock()

 {

         while(InterlockedCompareExchange(m_iFlag,1,0) != 0)
        {
             //不成功,表示其他线程已经加锁了
            //  自旋等待

          YieldProcessor(); 
        }

return 0

 }  

不支持yieldProcessor的系统上,可以使用计数: 


int lock()

{

    while(InterlockedCompareExchange(m_iFlag,1,0) != 0)

{

 int count = 1000;

while(--count);

}

return 0;

}


通常认为自旋容易产生活锁,因为如果1000个线程都 用count =1000 来等待的话,会在InterlockedCompareExchange函数里产生大量无用的竞争。改进如下:

int lock()

{

    while(InterlockedCompareExchange(m_iFlag,1,0) != 0)

{

srand(GetTickCount());

 int count = 500+rand()%500;

while(--count);

}

return 0;

}

自旋锁一般不使用在较长等待的情况下。 如果等待太长时间会怎么样呢? 这里肯定会太浪费CPU了。但我们长须处理长时间等待这种特殊情况:

 int Lock()

{

   int   iWastCount = 10;

    while(InterlockedCompareExchange(m_iFlag,1,0) != 0){


   if( --iWastCount<=0)

  {

          Sleep(0);

    } 

else {

srand(GetTickCount());

 int count = 500+rand()%500;

while(--count);

}


}

return 0;

}




                  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值