自旋锁的应用

通常自旋锁分三种: 纯自旋,队列自旋锁和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;

}




                  

你可能感兴趣的:(多线程,c++)