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

#ifndef _PTHREAD_RWLOCK_H

#define _PTHREAD_RWLOCK_H

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;        //写线程持有 -1 读线程持有 >0

}my_pthread_rwlock_t;



#define  RW_MAGIC    0x20190324



#define MY_PTHREAD_RWLOCK_INITIALIZER {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER,\

RW_MAGIC, 0, 0, 0}



typedef int my_pthread_rwlockattr_t;



int my_pthread_rwlock_init(my_pthread_rwlock_t *rw, my_pthread_rwlockattr_t *attr);

int my_pthread_rwlock_destroy(my_pthread_rwlock_t *rw);



int my_pthread_rwlock_rdlock(my_pthread_rwlock_t *rw);

int my_pthread_rwlock_wrlock(my_pthread_rwlock_t *rw);



int my_pthread_rwlock_unlock(my_pthread_rwlock_t *rw);



int my_pthread_rwlock_tryrdlock(my_pthread_rwlock_t *rw);

int my_pthread_rwlock_trywrlock(my_pthread_rwlock_t *rw);



/

//函数实现

//

int my_pthread_rwlock_init(my_pthread_rwlock_t *rw, my_pthread_rwlockattr_t *attr)

{

    int result;

    //由于本函数不支持给读写锁赋属性,故此处只检测attr是否为空指针的情况

    if(attr != NULL)

        return (EINVAL);

    //初始化互斥锁

    if( (result = pthread_mutex_init(&rw->rw_mutex, NULL)) != 0)

        goto err1;

    //初始化读条件变量

    if( (result = pthread_cond_init(&rw->rw_condreaders, NULL)) != 0)

        goto err2;

    //初始化写条件变量

    if( (result = pthread_cond_init(&rw->rw_condwriters, NULL)) != 0)

        goto err3;



    //初始化读线程等待个数

    rw->rw_nwaitreaders = 0;

    //初始化写线程等待个数

    rw->rw_nwaitwriters = 0;

    //初始化引用计数

    rw->rw_refcount = 0;

    //初始化magic

    rw->rw_magic = RW_MAGIC;



    return (0);



    //错误处理

    err3:

        pthread_cond_destroy(&rw->rw_condwriters);

    err2:

        pthread_cond_destroy(&rw->rw_condreaders);

    err1:

        return (result);

}



int my_pthread_rwlock_destroy(my_pthread_rwlock_t *rw)

{

    //出错检测

    if(rw->rw_magic != RW_MAGIC)

        return (EINVAL);



    //若引用计数不为零,或有读或写线程等待,则返回忙碌

    if(rw->rw_refcount != 0 || rw->rw_nwaitreaders != 0 || rw->rw_nwaitwriters != 0)

        return (EBUSY);



    //该释放的释放,该置空的置空

    pthread_mutex_destroy(&rw->rw_mutex);

    pthread_cond_destroy(&rw->rw_condreaders);

    pthread_cond_destroy(&rw->rw_condwriters);

    rw->rw_magic = 0;



    return (0);

}



int my_pthread_rwlock_rdlock(my_pthread_rwlock_t *rw)

{

    int result;

    //出错检测

    if(rw->rw_magic != RW_MAGIC)

        return (-1);



    //进入临界区

    if((result = pthread_mutex_lock(&rw->rw_mutex)) != 0)

        return result;



    //有线程持有写锁, 或有线程等待持有写锁,即无法获得读锁

    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;

    }



    //没有占用,取得读锁后引用计数加1,旋即释放互斥锁

    if(result == 0)

        rw->rw_refcount++;



    //退出临界区

    pthread_mutex_unlock(&rw->rw_mutex);

    return result;

}



int my_pthread_rwlock_tryrdlock(my_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->rw_refcount < 0 || rw->rw_nwaitwriters > 0)

        result = EBUSY;			/* held by a writer or waiting writers */

    else

        //否则将引用计数加1,获得读锁

        rw->rw_refcount++;		/* increment count of reader locks */



    //退出临界区

    pthread_mutex_unlock(&rw->rw_mutex);

    return(result);

}



int my_pthread_rwlock_wrlock(my_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);



    //有线程持有读锁或有线程持有唯一写锁(两者皆为引用计数不为零的情况)

    while (rw->rw_refcount != 0)

    {

        //增加线程等待获得写锁个数

        rw->rw_nwaitwriters++;

        //并使其投入睡眠

        result = pthread_cond_wait(&rw->rw_condwriters, &rw->rw_mutex);

        //减少线程等待获得读锁个数

        rw->rw_nwaitwriters--;

        if (result != 0)

            break;

    }

    //没有占用,取得写锁后引用计数置为-1,体现写锁的独占性,旋即释放互斥锁

    if (result == 0)

        rw->rw_refcount = -1;



    //退出临界区

    pthread_mutex_unlock(&rw->rw_mutex);

    return(result);

}



int my_pthread_rwlock_trywrlock(my_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->rw_refcount != 0)

        result = EBUSY;

    else

        //否则将引用计数加1,获得写锁

        rw->rw_refcount = -1;



    //退出临界区

    pthread_mutex_unlock(&rw->rw_mutex);

    return(result);

}



//释放一个读锁或者写锁

int my_pthread_rwlock_unlock(my_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->rw_refcount > 0) //准备释放读锁

        rw->rw_refcount--;

    else if(rw->rw_refcount == -1)  //准备释放写锁

        rw->rw_refcount = 0;

    else



    if(rw->rw_nwaitwriters > 0)

    {

        if(rw->rw_refcount == 0)    //一个写者等待

            result = pthread_cond_signal(&rw->rw_condwriters);

    }else if(rw->rw_nwaitreaders > 0)   //多个读者等待

        result = pthread_cond_broadcast(&rw->rw_condreaders);



    //退出临界区

    pthread_mutex_unlock(&rw->rw_mutex);

    return(result);

}

#endif // _PTHREAD_RWLOCK_H

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值