这次当我给面试官提及到读写锁的时候,详细问了我的读写锁,我知道怎么回事,用法,但是具体没实践过,听过的还是不要给面试官说了,不然又给自己挖坑。

   下面这个程序就是读写锁的程序,分别有两个读者,两个写着,当写着输入end的时候并且读者读到程序运行结束,里面的读写锁是动态初始化,最后用pthread_join(),主要主线程等待子线程运行完她才可以结束。对于现在锁,我才感觉到都是有套路的,都被玩坏了。初始化,处理的,最后是销毁的。此外,我还遇到的一个问题是当时忘记在写线程忘记休眠sleep,结果一直让我写,写,写,那么她就一直拿着cpu写,就算输入end也就结束不了,因为读线程根本执行不到。


#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <bits/pthreadtypes.h>


#define  WORK_SIZE  1024

static  pthread_rwlock_t  rwlock;

char work_area[WORK_SIZE];
int time_to_exit;

void *thread_to_read_o(void *arg);
void *thread_to_read_t(void *arg);
void *thread_to_write_o(void *arg);
void *thread_to_write_t(void *arg);


void *thread_to_read_o(void *arg)
{
    printf("thread read one try to get lock\n");

    pthread_rwlock_rdlock(&rwlock);
    while(strncmp("end",work_area,3) != 0){
        printf("this is thread read one\n");
        printf("the characters is %s\n",work_area);
        pthread_rwlock_unlock(&rwlock);
        sleep(2);
        pthread_rwlock_rdlock(&rwlock);
        while(work_area[0] == '\0'){
           pthread_rwlock_unlock(&rwlock);
           sleep(2);
           pthread_rwlock_rdlock(&rwlock);
        }
    }
    pthread_rwlock_unlock(&rwlock);
    time_to_exit = 1;
    pthread_exit(0);
}

void *thread_to_read_t(void *arg)
{
    printf("thread read one try to get lock\n");

    pthread_rwlock_rdlock(&rwlock);
    while(strncmp("end",work_area,3) != 0){
        printf("this is thread read two\n");
        printf("the characters is %s\n",work_area);
        pthread_rwlock_unlock(&rwlock);
        sleep(5);
        pthread_rwlock_rdlock(&rwlock);
        while(work_area[0] == '\0'){
             pthread_rwlock_unlock(&rwlock);
             sleep(5);
             pthread_rwlock_rdlock(&rwlock);
        }
    }
    pthread_rwlock_unlock(&rwlock);
    time_to_exit = 1;
    pthread_exit(0);
}
void *thread_to_write_o(void *arg)
{
    printf("this is write thread one try to get lock\n");
    while(!time_to_exit){
           pthread_rwlock_wrlock(&rwlock);
           printf("this is write thread one\n,input some text,enter 'end'  to finish\n");
           fgets(work_area,WORK_SIZE,stdin);
           pthread_rwlock_unlock(&rwlock);
           sleep(15); // forget sleep,so write always
    }

    pthread_rwlock_unlock(&rwlock);
    pthread_exit(0);
}
void *thread_to_write_t(void *arg)
{
    sleep(10);
    while(!time_to_exit){
       pthread_rwlock_wrlock(&rwlock);
       printf("this is write thread two\n input some text,enter 'end' to finish\n");
       fgets(work_area,WORK_SIZE,stdin);
       pthread_rwlock_unlock(&rwlock);
       sleep(20);
    }
    pthread_rwlock_unlock(&rwlock);
    pthread_exit(0);
}




int main(int argc,char *argv[])
{
    int retval;
    pthread_t a_thread,b_thread,c_thread,d_thread;
    void *thread_result;

    retval = pthread_rwlock_init(&rwlock,NULL);
    if(retval != 0){
          //  error
          exit(1);
    }

    retval = pthread_create(&a_thread,NULL,thread_to_read_o,NULL);
    if(retval != 0){
          //  error
          exit(1);
    }

    retval = pthread_create(&b_thread,NULL,thread_to_read_t,NULL);
    if(retval != 0){
          //  error
          exit(1);
    }

    retval = pthread_create(&c_thread,NULL,thread_to_write_o,NULL);
    if(retval != 0){
          //  error
          exit(1);
    }
    retval = pthread_create(&d_thread,NULL,thread_to_write_t,NULL);
    if(retval != 0){
          //  error
          exit(1);
    }

    // suspend main thread
    pthread_join(a_thread,NULL);

    pthread_join(b_thread,NULL);

    pthread_join(c_thread,NULL);

    pthread_join(d_thread,NULL);


    // destroy rwlock
    pthread_rwlock_destroy(&rwlock);

    printf("main thread will exit\n");

    return 0;
}

  


关于读写锁的第二个程序,主要是测试读锁和写锁哪个更加优先的问题,linux默认的是读者优先

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

pthread_rwlock_t rwlock;

void *readers(void *arg)
{
    pthread_rwlock_rdlock(&rwlock);
    printf("readers %d got the lock\n",(int)arg);
    pthread_rwlock_unlock(&rwlock);
}

void *writes(void *arg)
{
    pthread_rwlock_wrlock(&rwlock);
    printf("write %d got the lock\n",(int)arg);
    pthread_rwlock_unlock(&rwlock);
}

int main(int argc,char *argv[])
{
    int retval,i;
    pthread_t writer_id,reader_id;
    pthread_attr_t attr;
    int nreadercount = 1;
    int nwritercount = 1;

    if(argc != 2){
         // error
         exit(1);
    }

    retval = pthread_rwlock_init(&rwlock,NULL);
    if(retval != 0){
        //error
        exit(2);
    }

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);


 //   pthread_rwlock_wrlock(&rwlock);
    pthread_rwlock_rdlock(&rwlock);
    for(i = 0; i < atoi(argv[1]);i++){
       if(random() % 2){
            pthread_create(&reader_id,&attr,readers,(void *)nreadercount);
            printf("create reader %d\n",nreadercount++);
       }else{
            pthread_create(&writer_id,&attr,writes,(void *)nwritercount);
            printf("create writer %d\n",nwritercount++);
       }
    }

  //  sleep(10);
    pthread_rwlock_unlock(&rwlock);
    sleep(10);
    return 0;
}

在上面的程序中如果有这个pthread_rwlock_wrlock(&rwlock);那么就算读者先加锁了,这时写者来了,那么再来的读者就不能加锁了,写者一直等到第一个读者结束后自己在加锁。理论是这样的,但是实际的结果,确实有点偏差,先看图


第6个读者先得到了锁,我感觉这个里面做了优化,前9个因为加锁的缘故只能先创建完之后再执行线程,最后一个readers 6,内核已经知道迟早readers 6要执行的,既然内核现在拿着这个reader 6,内核就顺便执行,才不管你有么有pthread_rwlock_wrlock(&rwlock)


在上面的程序中如果有这个pthread_rwlock_rdlock(&rwlock),运行结果



如果有什么问题,欢迎指正

Logo

更多推荐