UNIX网络编程(八)读写锁

8.1概述

只要没有线程在修改某个给定的数据,那么任意数目的线程都可以拥有该数据的读访问权。仅当没有其他线程在读或者修改某个给定的数据时,当前线程才能修改它

某些应用中,读数据比修改数据频繁,这些应用更加适用读写锁。这种对于某个给定资源的共享访问也称为共享-独占锁

8.2获取与释放读写锁

读写锁数据类型为pthread_rwlock_t.如果这个类型的变量是静态分配的,可通过给它赋常值PTHREAD_RWLOCK_INITIALIZER来初始化它

#include<pthread.h>
int pthread_rwlock_rdlock(pthread_rwlock_t *rwptr)
int pthread_rwlock_wrlock(pthread_rwlock *rwptr)
int pthread_rwlock_unlock(pthread_rwlock *rwptr)

下面两个函数尝试获取一个读出锁或写入锁,但是如果不能马上获得,那就返回一个EBUSY错误,而不是把调用线程投入睡眠

int pthread_rwlock_tryrdlock(pthread_rwlock *rwptr)
int pthread_rwlock_trywrlock(pthread_rwlock *rwptr)

8.3读写锁属性

读写锁变量可以通过pthread_rwlock_init来动态初始化,当一个线程不再需要某个读写锁时,可以调用pthread_rwlock_destory啊含糊摧毁它

int  pthread_rwlock_init(pthread_rwlock_t *rwptr,const pthread_rwlockattr_t *attr)
int pthread_rwlock_destory(pthread_rwlock_t *rwptr)
初始化时,attr是个空指针,那么读写锁使用默认属性。如果要赋予它非默认属性,需要使用下面两个函数

int pthread_rwlockattr_init(pthread_rwlockattr_t *attr)

int pthread_rwlockattr_destory(pthread_rwlockattr *attr)

当期定义了唯一的属性是PTHREAD_PROCESS_SHARED,它指定读写锁在不同进程间共享,二不仅仅是在单个进程内的不同线程共享,下面两个函数分别获取和设置这个属性

int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *attr,int *valptr)

int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int value)

8.4使用互斥锁和条件变量实现读写锁


只需要互斥锁和条件变量就可以实现读写锁,下面的实现优先考虑等待着的写入者。

 

typedef struct{
pthread_mutex_t rw_mutex;
pthread_cond_t rw_condreaders;
pthread_cond_t rw_condwriters;
int rw_magic;
int rw_nwaitreaders;
int rw_nwaitwriters;
int rw_refcount;
}pthread_rwlock_t;
int pthread_rwlock_rdlock(pthread_rwlock_t *rw)
{
int result;
if(rw->rw_magic!=RW_MAGIC)
    return (EINVAL);
if((resulr=pthread_mutex_lock(&rw->rw_mutex))!=0)
    return result;
while(rw->refcount<0||rw->nwaitwriters>0)
{
    
    
rw->rw_nreaders++;
   
result=pthread_cond_wait(&rw->rw_condreaders,&rw->rw_mutex);
   
 rw->rw_nreaders--;

if(result!=0)
        break;




}
if(result==0)
    rw->rw_recount++;
pthread_mutex_unlock(&rw->rw_mutex);
return (result);
}


 int pthread_rwlock_tryrdlock(pthread_rwlock_t *rw)
 {
     int result;
     if(rw->rw_magic!=RW_MAGIC)
        return(EINVAL);
     if((result=pthread_mutex_lock(&rw->rw_mutex)!=0)
        return(result);
        if(rw->rwfcount<0||rw->nwaitwriters>0)
            return EBUSY;
     else 
        rw->rw_fcount++;
     pthread_mutex_unlock(&rw->rw_mutex);
 }
 int pthread_rwlock_wrlock(pthread_rwlock_t *rw)
 {
     int result;
     if(rw->rw_magic!=MAGIC)
        return (EVIAL);
     if((result=pthread_mutex_lock(&rw->rw_mutex))!=0)
        return(result);
     while(rw->rw_fcount!=0)
 {
     
     rw->rw_nwaitwriters++;
     result=pthread_cond_wait(&rw->rw_condwriters);
     rw->rw_nwaitwriters++;
     if(result!=0)
        break;
 }
 if(result==0)
    rw->rw_fcount=-1;
 pthread_mutex_unlock(&rw->rw_mutex);
 return result;
 }
 int pthread_rwlock_unlock(pthread_rwlock_t *rw)
 {
     int result;
     if(rw->rw_magic!=MAGIC)
        return (EINVAL);
     if((result=pthread_mutex_lock(&rw->rw_mutex)!=0)
        return result;
        if(rw->rw_fcount>0)
            rw->rw_fcount--;
     else if(rw->rw_fcount=-1)
        rw->rw_fcount=0;
     else
     ...........
     if(rw->rw_nwaitwriters>0)
     {
         if(rw->rw_fcount=0)
         result=pthread_cond_sigal(&rw->rw_condwriters);
     }
     else if(rw->rw_nwaitreaders>0)
        result=pthread_cond_broadcast(&rw->rw_condreaders);
 pthread_mutex_unlock(rw->rw_mutex);
 return result;

 }



8.5线程取消


如果pthread_rwlock_rdlock的调用线程阻塞在pthread_cond_wait调用上,随后被统一进程中的其他线程取消,它就在仍然持有互斥锁的情况下终止

我们可以在原有的代码中加入两行

rw->rw_nreaders++;
pthread_cleanup_push(rwlock_cancelrdwait,(void *arg))//添加清理处理程序    
result=pthread_cond_wait(&rw->rw_condreaders,&rw->rw_mutex);
pthread_cleanup_pop(0);   //删除清理处理程序
 rw->rw_nreaders--;


 

第一行代码建立一个清理处理程序,如果pthread_cond_wait返回,第二行新代码就要删除这个清理处理程序
下面看一下清理处理程序的代码

void rwlock_cancelrdwait(void *arg)
{
pthread_rwlock_t *rw;
rw=arg;
rw->rw_nwaitreaders--;
pthread_mutex_unlock(&rw->rw_mutex);



}


第一行代码建立一个清理处理程序,如果pthread_cond_wait返回,第二行新代码就要删除这个清理处理程序
下面看一下清理处理程序的代码

如果·pthread_rwlock_rdlock的调用线程在阻塞于该函数pthread_cond_wait期间被取消,它就不会从该函数返回,而是调用清理处理程序


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值