您的位置:首页 > 运维架构 > Linux

关于linux的读写锁

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

   下面这个程序就是读写锁的程序,分别有两个读者,两个写着,当写着输入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),运行结果



如果有什么问题,欢迎指正
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: