1. 程式人生 > >我常用的 C++ 讀寫鎖

我常用的 C++ 讀寫鎖

鎖操作是為了執行緒安全,下面寫一個我常用的 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;
}