Linux 下的线程读写锁

有一种写优先读写锁,有如下特点:
1)多个读者可以同时进行读
2)写者必须互斥(只允许一个写者写,也不能读者写者同时进行)
3)写者优先于读者(一旦有写者,则后续读者必须等待,唤醒时优先考虑写者)

在Solaris 中直接提供了读写锁, 但是在Linux 中只提供了线程的读写锁, 这里记录了一些读写锁的资料.

1.Solaris .vs. Linux Posix 库函数

Solaris 库(lib 线程)Linux POSIX 库(libp 线程)操作
sema_destroy()sem_destroy()销毁信号状态。
sema_init()sem_init()初始化信号。
sema_post()sem_post()增加信号。
sema_wait()sem_wait()阻止信号计数。
sema_trywait()sem_trywait()减少信号计数。
mutex_destroy()pthread_mutex_destroy()销毁或禁用与互斥对象相关的状态。
mutex_init()pthread_mutex_init()初始化互斥变量。
mutex_lock()pthread_mutex_lock()锁定互斥对象和块,直到互斥对象被释放。
mutex_unlock()pthread_mutex_unlock()释放互斥对象。
cond_broadcast()pthread_cond_broadcast()解除对等待条件变量的所有线程的阻塞。
cond_destroy()pthread_cond_destroy()销毁与条件变量相关的任何状态。
cond_init()pthread_cond_init()初始化条件变量。
cond_signal()pthread_cond_signal()解除等待条件变量的下一个线程的阻塞。
cond_wait()pthread_cond_wait()阻止条件变量,并在最后释放它。
rwlock_init()pthread_rwlock_init()初始化读/写锁。
rwlock_destroy()pthread_rwlock_destroy()锁定读/写锁。
rw_rdlock()pthread_rwlock_rdlock()读取读/写锁上的锁。
rw_wrlock()pthread_rwlock_wrlock()写读/写锁上的锁。
rw_unlock()pthread_rwlock_unlock()解除读/写锁。
rw_tryrdlock()pthread_rwlock_tryrdlock()读取非阻塞读/写锁上的锁。
rw_trywrlock()pthread_rwlock_trywrlock()写非阻塞读/写锁上的锁。


2.使用mutex 来实现

设置三个互斥信号量:
rwmutex        用于写者与其他读者/写者互斥的访问共享数据
rmutex        用于读者互斥的访问读者计数器readcount
nrmutex        用于写者等待已进入读者退出,所有读者退出前互斥写操作

var   rwmutex,rmutex,nrmutex:semaphore:=1,1,1;  
int   readcount=0;

cobegin
    reader begin
        P(rwmutex);
        P(rmutex);
        readcount++;
        if (readcount == 1) P(nrmutex);  //有读者进入,互斥写操作
        V(rmutex);
        V(rwmutex);  //及时释放读写互斥信号量,允许其它读、写进程申请资源读数据;
        
        P(rmutex);
        readcount--;
        if(readcount == 0) V(nrmutex);  //所有读者退出,允许写更新
        V(rmutex);
    End
    
    writer begin
        P(rwmutex);    //互斥后续其它读者、写者
        P(nrmutex);    //如有读者正在读,等待所有读者读完
        写更新;
        V(nrmutex);    //允许后续新的第一个读者进入后互斥写操作  
        V(rwmutex);    //允许后续新读者及其它写者
    End  
coend  

3. 利用pthread_cond_* & pthread_mutex_* 实现rw_lock

#include  < pthread.h >
#include 
< cstdlib >
#include 
< ctime >
#include 
< iostream >
using   namespace  std;

class  RWLock {

private  :
    pthread_mutex_t cnt_mutex;
    pthread_cond_t rw_cond;
    
int  rd_cnt, wr_cnt;

    RWLock(
const  RWLock & );
    RWLock
&   operator =  ( const  RWLock & );

public  :
    RWLock(): rd_cnt(
0 ),wr_cnt( 0 )
        {
            pthread_mutex_init(
& cnt_mutex, NULL);
            pthread_cond_init(
& rw_cond, NULL);
        }

    
void  get_shared_lock()
        {
            pthread_mutex_lock(
& cnt_mutex);
            
while  (wr_cnt  > 0 )
                {
                    pthread_cond_wait(
& rw_cond, & cnt_mutex);
                }
            rd_cnt
++ ;
            pthread_mutex_unlock(
& cnt_mutex);
        }

    
void  release_shared_lock()
        {
            pthread_mutex_lock(
& cnt_mutex);
            rd_cnt
-- ;
            
if  ( 0   ==  rd_cnt)
                {
                    pthread_cond_signal(
& rw_cond);
                }
            pthread_mutex_unlock(
& cnt_mutex);
        }

    
void  get_exclusive_lock()
        {
            pthread_mutex_lock(
& cnt_mutex);
            
while  (rd_cnt + wr_cnt > 0 )
                {
                    pthread_cond_wait(
& rw_cond, & cnt_mutex);
                }
            wr_cnt
++ ;
            pthread_mutex_unlock(
& cnt_mutex);
        }

    
void  release_exclusive_lock()
        {
            pthread_mutex_lock(
& cnt_mutex);
            wr_cnt
-- ;
            pthread_cond_broadcast(
& rw_cond);
            pthread_mutex_unlock(
& cnt_mutex);
        }

    
~ RWLock()
        {
            pthread_mutex_destroy(
& cnt_mutex);
            pthread_cond_destroy(
& rw_cond);
        }
};

class  Test
{

private  :    
    RWLock 
lock ;
    
    
static   void *  shared_task_handler( void *  arg)
        {
            Test
*  testptr  =  static_cast < Test *> (arg);

            testptr
-> lock .get_shared_lock();
            
// do the shared task here
            testptr -> lock .release_shared_lock();
        }


    
static   void   *  exclusive_task_handler( void   *  arg)
        {
            Test
*  testptr  =  static_cast < Test *> (arg);
            testptr
-> lock .get_exclusive_lock();
            
// do the exclusive task here
            testptr -> lock .release_exclusive_lock();
        }

public  :
    typedef 
void *  ( * ThreadFunc) ( void * );

    
void  start()
        {
            srand(time(NULL));

            
const   int  THREADS_NO = rand() % 100 ;
            pthread_t
*  threads  =   new  pthread_t[THREADS_NO];

            
for ( int  i = 0 ; i < THREADS_NO; i ++ )
                {
                    ThreadFunc tmpfunc 
=  rand() % 2 ?  shared_task_handler : exclusive_task_handler;
                    
if  (pthread_create(threads + i,NULL,tmpfunc, this ))
                        {
                            cerr 
<<   " pthread_create fails "   <<  endl;
                            exit(
1 );
                        }
                }

            
for ( int  i = 0 ; i < THREADS_NO; i ++ )
                {
                    pthread_join(threads[i],NULL);
                }

            delete[] threads;
        }
};

int  main()
{
    Test tmptest;
    tmptest.start();
}

--------------------------
参考:
Solaris 執行緒與同步機制之實例
Posix线程编程指南
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值