读写锁的实现

#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdlib.h>
#define NUM 10 //定义循环缓冲区大小为10
pthread_mutex_t wlock,rlock;
pthread_mutex_t rcount_lock,wcount_lock;
sem_t nowriter,wfinished;
int read_count,write_count;
int buf[]={1,2,3,4,5,6,7,8,9,10};
void* writer(void *d)
{
    int data = (int)d;
    if( pthread_mutex_trylock(&wlock) == 0)
    {//加写锁成功
        printf("writer %d get wlock\n",data);
        for(int i = 0;i < 10;i++)
        {
            buf[i]=data;
            //sleep(1);
        }
        pthread_mutex_unlock(&wlock);
        printf("writer %d finished writing\n",data);
        pthread_mutex_lock(&wcount_lock);
        if(write_count == 0)//没有写者等待,唤醒读者
        {
            sem_post(&nowriter);
            printf("writer %d is the last writer,wake up a reader\n",data);
        }
        else//有写者等,唤醒一个等待的写者
        {
            printf("writer %d detect %d writers waiting,wake up a writer\n",data,write_count);
            sem_post(&wfinished);
        }
        pthread_mutex_unlock(&wcount_lock);
    }
    else//加写锁失败,当前有写者或读者运行,应加入写者等待队列
    {

        pthread_mutex_lock(&wcount_lock);
        write_count++;//等待写者数加一
        pthread_mutex_unlock(&wcount_lock);
        printf("writer %d get wlock fail,block to wait,total %d waiting \n",data,write_count);
WAIT:  sem_wait(&wfinished); //加入等待队列
        //一个写者被唤醒,被唤醒后的写者区分于新加入写者,可能与新加入的写者竞争失败
        if(pthread_mutex_trylock(&wlock) == 0)
        {
                printf("writer %d get wlock\n",data);
                for(int i = 0;i < 10;i++)
                {
                    buf[i]=data;
                    //sleep(1);
                }
            pthread_mutex_unlock(&wlock);

            printf("writer %d waked up and finised writing\n",data);

            pthread_mutex_lock(&wcount_lock);
                printf("writer %d get wcount_lock\n",data);
                write_count--;//等待写者数减一
                if(write_count == 0)//最后一个写者唤醒等待服务的读者
                    {
                        printf("writer %d is the last writer,wake up a reader\n",data);
                        sem_post(&nowriter);
                    }
                else //唤醒等待服务的写者
                    {
                        sem_post(&wfinished);
                        printf("writer %d detect %d writers waiting,wake up a writer\n",data,write_count);
                    }
            pthread_mutex_unlock(&wcount_lock);
        }
        else
        {//被新加入的写者抢占,重新加入等待队列
            printf("writer %d get wlock fail,block to wait\n",data);
            goto WAIT;
        }
    }
return NULL;
}
void* reader(void* id)
{
READER:
    sem_wait(&nowriter);//等待没有写者
    if(0 == pthread_mutex_trylock(&wlock))
    {//第一个读者获取到写锁
        printf("reader %d get wlock\n",(int)id);
        read_count = 1;
        pthread_mutex_lock(&wcount_lock);
        if(write_count == 0)
            sem_post(&nowriter);//没有写者等待服务,让第二个读者进来
        pthread_mutex_unlock(&wcount_lock);
        //read file
        printf("reader %d read:",(int)id);
        for(int i = 0;i < 10;i++)
            {
                printf("%d ",buf[i]);
            //    sleep(1);
            }
        printf("\n");
        printf("reader %d finished reading\n",(int)id);
        pthread_mutex_lock(&rcount_lock);
        read_count --;
        if(read_count == 0)
        {
            printf("reader %d is the last reader\n",(int)id);
            pthread_mutex_unlock(&wlock);
            pthread_mutex_lock(&wcount_lock);
            if(write_count > 0)
            {
                sem_post(&wfinished);
                printf("reader %d is the last reader,wake up 1 in %d waiting writers\n",(int)id,write_count);
            }
            pthread_mutex_unlock(&wcount_lock);
        }
        pthread_mutex_unlock(&rcount_lock);
    }
    else
    {//失败的原因一个是有写者在写,或者已经有读者在读
        printf("reader %d get wlock fail\n",(int)id);
        pthread_mutex_lock(&rcount_lock);
        if(read_count > 0)
        {//有读者的情况
                read_count++;
            pthread_mutex_unlock(&rcount_lock);
            pthread_mutex_lock(&wcount_lock);
            if(write_count == 0)
                sem_post(&nowriter);//没有写者等待服务,让更多读者进来
            pthread_mutex_unlock(&wcount_lock);
            //read file;
            printf("reader %d:",(int)id);
            for(int i = 0;i < 10;i++)
                printf("%d ",buf[i]);
            printf("\n");
            printf("reader %d finished reading\n",(int)id);
            pthread_mutex_lock(&rcount_lock);
                read_count--;//读完减一
                if(read_count == 0)
                {
                    printf("reader %d is the last reder \n",(int)id);
                    pthread_mutex_unlock(&wlock);//最后一个读者释放写锁
                    pthread_mutex_lock(&wcount_lock);
                    if(write_count > 0)
                    {
                        sem_post(&wfinished);
                        printf("reader %d is the last reader,wake up 1 in %d waiting writers\n",(int)id,write_count);
                    }
                    pthread_mutex_unlock(&wcount_lock);
                }
            pthread_mutex_unlock(&rcount_lock);
        }
        else
        {//有写者的情况,继续等待
            goto READER;
        }
    }
    return NULL;
}
void init()
{
    read_count = write_count = 0;
    pthread_mutex_init(&wlock,NULL);
    pthread_mutex_init(&wcount_lock,NULL);
    pthread_mutex_init(&rcount_lock,NULL);
    sem_init(&wfinished,0,0);
    sem_init(&nowriter,0,1);
}
int main(void)
{
    init();
    pthread_t r1,r2,r3,w1,w2,w3;
    pthread_create(&r1,0,reader,(void*)1);
   pthread_create(&r2,0,reader,(void*)2);
pthread_create(&w1,0,writer,(void*)1);
   pthread_create(&w2,0,writer,(void*)2);
   pthread_create(&w3,0,writer,(void*)3);
   pthread_create(&r3,0,reader,(void*)3);
   pthread_join(r1,NULL);
    printf("main:r1 finished\n");
    pthread_join(r2,NULL);
    printf("main:r2 finished\n");
   pthread_join(w1,NULL);
   printf("main:w1 finished\n");
   pthread_join(w2,NULL);
   printf("main:w2 finished\n");
   pthread_join(w3,NULL);
   printf("main:w3 finished\n");
   pthread_join(r3,NULL);
   printf("main:r3 finished\n");
   printf("buf data are:");
   for(int i = 0;i < 10;i++)
    printf("%d ",buf[i]);
printf("\n");
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值