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


//具体参阅:《Unix网络编程》卷2,进程间通信。利用条件变量和互斥锁实现读写锁。

struct pthread_rwlock_t
{
    pthread_mutex_t rw_mutex; //每一步获取读写锁,都要两次操作,上锁和解锁。每一步释放读写锁,也要两次操作,上锁和解锁。
    pthread_cond_t rw_condreaders;
    pthread_cond_t rw_condwritres;
    int rw_magic;
    int rw_nwaitreaders;//等待获取读锁的进程。
    int rw_nwaitwriters;//等待获取写锁的进程。
    int rw_refcount;//读写锁的当前状态,-1表示它是一个写入锁(任意时刻这样的锁只能有一个),为n(n>0)时,有n个进程正在同时读。
};

//以下是实现框架。大致思路日下:先判断当前状态rw_refcount和排队等待获取锁的waiters,再决定“获取锁”或者“加入等待,条件等待”.


//获取读锁
void pthread_rwlock_rdlock()
{
    result=pthread_mutex_lock(&rw->rw_mutex);

    while(rw->rw_refcount<0||rw->rw_nwaitwriters>0){
        rw->rw_nwaitreaders++;
        result=pthread_cond_wait(&rw->rw_condreaders,&rw->rw_mutex);
        rw->rw_nwaitreaders--;
        if(result!=0)
            break;
    }

    if(result==0)
        rw->rw_refcount++;

     result=pthread_mutex_unlock(&rw->rw_mutex);
}


//获取写锁
void pthread_rwlock_rdlock()
{
    result=pthread_mutex_lock(&rw->rw_mutex);

    while(rw->rw_refcount!=0){
        rw->rw_nwaitwriters++;
        result=pthread_cond_wait(&rw->rw_condwritres,&rw->rw_mutex);
        rw->rw_nwaitwriters--;
        if(result!=0)
            break;
    }

    if(result==0)
        rw->rw_refcount=-1;

     result=pthread_mutex_unlock(&rw->rw_mutex);

}


//释放读写锁。用一个统一释放函数即可。
void pthread_rwlock_rdlock()
{
    result=pthread_mutex_lock(&rw->rw_mutex);

    if(rw->rw_refcount>0)
        rw->rw_refcount--;
    else if(rw->rw_refcount==-1)
        rw->rw_refcount=0;
    else 
        throw error; //在释放锁时rw->rw_refcount=0判断条件的出现是不可能的,因为一旦加锁,它只可能两种状态,-1和1,2,3....
    
    if(rw->rw_nwaitwriters>0)//为什么要先判断是否有等待写入者,因为如果有大量的读入者试图获取锁时,可能导致写入者永远无机会获取
        if(rw->rw_refcount==0)
            result=pthread_cond_signal(&rw->rw_condwritres);//一定要先给写入者机会,否则,写入者可能没机会获取锁。
    else if(rw->rw_nwaitreaders>0)
        result=pthread_cond_broadcast(&rw->rw_condreaders);


     result=pthread_mutex_unlock(&rw->rw_mutex);

}

你可能感兴趣的:(Unix网络编程)