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

main函数

test.c

#include<stdio.h>
#include<unistd.h>
#include<pthread.h>

#include"rwlock.h"

my_pthread_rwlock_t rwlock = MY_PTHREAD_RWLOCK_INITIALIZER;

#define N 5

void* thread_fun(void *arg)
{
        my_pthread_rwlock_wrlock(&rwlock);
        printf("main thread get wrlock,\n");
        sleep(12);
        my_pthread_rwlock_unlock(&rwlock);

}

void* thread_fun1(void *arg)
{
        int index = *(int*)arg;
        printf("This is [%d]thread get rdlock.\n",index);
        my_pthread_rwlock_rdlock(&rwlock);
        printf("[%d] thread get rdlock.\n",index);
        my_pthread_rwlock_unlock(&rwlock);

}

void* thread_fun2(void *arg)
{
        int index = *(int*)arg;
        printf("This is [%d] thread get wrlock.\n",index);
        my_pthread_rwlock_wrlock(&rwlock);
        printf("[%d] thread get wrlock.\n",index);
        my_pthread_rwlock_unlock(&rwlock);

}

int main()
{
    pthread_t tid,tid1[N],tid2[N];

    pthread_create(&tid, NULL, thread_fun, NULL);

    int i;
    for(i=0; i<N; ++i)
    {
        pthread_create(&tid1[i], NULL, thread_fun1, &i);
        sleep(1);
    }
    for(i=0; i<N; ++i)
    {
        pthread_create(&tid2[i], NULL, thread_fun2, &i);
        sleep(1);
    }

    pthread_join(tid, NULL);
    for(i=0; i<N; ++i)
    {
        pthread_join(tid1[i], NULL);
        pthread_join(tid2[i], NULL);
    }
    return 0;
}

写锁优先

rwlock.h

#ifndef _RWLOCK_H
#define _RWLOCK_H

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<pthread.h>

enum {EINVAL=1};

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;
}my_pthread_rwlock_t;

#define RW_MAGIC 0x20171108

#define MY_PTHREAD_RWLOCK_INITIALIZER {PTHREAD_MUTEX_INITIALIZER,\
                                       PTHREAD_COND_INITIALIZER,\
                                       PTHREAD_COND_INITIALIZER,\
                                       RW_MAGIC,0,0,0}

//void my_pthread_rwlock_init();
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_rdlock(my_pthread_rwlock_t *rw)
{
    int result;
    if(rw->rw_magic != RW_MAGIC)
        return EINVAL;
    if((result = pthread_mutex_lock(&rw->rw_mutex)) != 0)  //锁成功返回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 != 1)
            break;
    }
    if(result == 0)
        rw->rw_refcount++;

    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;
    }
    if(result == 0)
        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
        printf("unlock rwlock error: rw_refcount = %d\n", rw->rw_refcount);

    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

运行结果:
这里写图片描述

读锁优先

rwlock.h

#ifndef _RWLOCK_H
#define _RWLOCK_H

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<pthread.h>

enum {EINVAL=1};

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;
}my_pthread_rwlock_t;

#define RW_MAGIC 0x20171108

#define MY_PTHREAD_RWLOCK_INITIALIZER {PTHREAD_MUTEX_INITIALIZER,\
                                       PTHREAD_COND_INITIALIZER,\
                                       PTHREAD_COND_INITIALIZER,\
                                       RW_MAGIC,0,0,0}

//void my_pthread_rwlock_init();
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_rdlock(my_pthread_rwlock_t *rw)
{
    int result;
    if(rw->rw_magic != RW_MAGIC)
        return EINVAL;
    if((result = pthread_mutex_lock(&rw->rw_mutex)) != 0)  //锁成功返回0
        return result;

    while(rw->rw_refcount < 0 ) //被写锁占用或者读锁优先的情况
    {
        rw->rw_nwaitreaders++;
        result = pthread_cond_wait(&rw->rw_condreaders,&rw->rw_mutex);
        rw->rw_nwaitreaders--;
        if(result != 1)
            break;
    }
    if(result == 0)
        rw->rw_refcount++;

    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;
    }

    if(result == 0)
        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
        printf("unlock rwlock error: rw_refcount = %d\n", rw->rw_refcount);

    if(rw->rw_nwaitreaders > 0)
        result = pthread_cond_broadcast(&rw->rw_condreaders);
    else if(rw->rw_nwaitwriters > 0)
    {
        if(rw->rw_refcount == 0)
            result = pthread_cond_signal(&rw->rw_condwriters);
    }
    pthread_mutex_unlock(&rw->rw_mutex);
    return result;
}
#endif

运行结果:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/Sanjiye/article/details/78484395
今日推荐