我常用的 C++ 读写锁

来源:互联网 发布:百度贴吧衰落知乎 编辑:程序博客网 时间:2024/06/05 05:35

锁操作是为了线程安全,下面写一个我常用的 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;}
0 0
原创粉丝点击