我常用的 C++ 讀寫鎖
阿新 • • 發佈:2019-01-03
鎖操作是為了執行緒安全,下面寫一個我常用的 C++ 自旋鎖,簡單高效。
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/time.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
template<typename T>
class RSpinLock
{
public :
RSpinLock( T * addr ) : m_addr(addr)
{
while( true )
{
T old = * m_addr;
old &= (T)~1;
if( __sync_bool_compare_and_swap( m_addr, old, old | 2 ) ) //set reader
{
__sync_fetch_and_add( m_addr, 4 ); //add a reader
break;
}
}
}
~RSpinLock( )
{
__sync_fetch_and_sub( m_addr, 4 );
__sync_bool_compare_and_swap( m_addr, 2, 0 ); //clear reader
}
private : T * m_addr;
};
template<typename T>
class WSpinLock
{
public:
WSpinLock( T * addr ) : m_addr(addr)
{
while( !__sync_bool_compare_and_swap( m_addr, 0, 1 ) );
}
~WSpinLock( )
{
*m_addr = 0;
}
private: T * m_addr;
};
寫自旋鎖中的 __sync_bool_compare_and_swap(m_addr, 0, 1)
函式表示當呼叫建構函式時將 m_addr
指向的值為 0 時,將其交換為 1 並返回 ture
,相當於某個程序拿到了鎖。
當另外的程序呼叫建構函式時,由於 m_addr
已經指向 1,__sync_bool_compare_and_swap(m_addr, 0, 1)
則返回 false
,那麼這個程序就被鎖在了 while 迴圈中。直到拿到鎖的程序呼叫解構函式將 m_addr
指向的值再次修改為 0,釋放調鎖。
需要上鎖時直接在程式碼塊中構造 WSpinLock 物件即可。
{
WSpinLock<uint32_t> locker( &m_bf_meta.Ptr()->tItemMeta[index].iLock );
/* 上鎖後的操作 */
}// 跳出程式碼塊後,自動呼叫 locker 解構函式,釋放掉鎖
讀自旋鎖測試程式碼如下:
#include "RWSpinLock.h"
#include <stdio.h>
int main()
{
char x = 0;
{
RSpinLock<char> l1(&x);
{
RSpinLock<char> l2(&x);
{
RSpinLock<char> l3(&x);
printf("%d\n", x);
}
printf("%d\n", x);
}
printf("%d\n", x);
}
printf("%d\n", x);
return 0;
}