读写锁
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了读写锁相关的知识,希望对你有一定的参考价值。
1、读写锁
互斥锁:试图进入临界区的所有其他进程都阻塞住。
读写锁:获取读写锁用于读和获取读写锁用于写作区分。
读写锁分配规则:
(1)、读锁:共享锁,此时可以有多个读锁,但是没有写锁。
(2)、写锁:独占锁,此时在也没有任何的写/读锁。
(3)、读写锁中,写锁优先抢占资源。
2、编程实现
需要使用:pthread_rwlock_t rwlock //定义了一个读写锁变量;
使用的API为:
函数 | 说明 |
pthread_rwlock_wrlock() | 写锁 |
pthread_rwlock_rdlock() | 读锁 |
pthread_rwlock_unlock() | 解锁 |
代码实现:
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<string.h> #include<pthread.h> pthread_rwlock_t rwlock; void* fun1(void *arg){ pthread_rwlock_wrlock(&rwlock); printf("This is fun1, wlock\n"); sleep(2); pthread_rwlock_unlock(&rwlock); } void* fun2(void *arg){ pthread_rwlock_rdlock(&rwlock); printf("This is fun2, rlock\n"); pthread_rwlock_unlock(&rwlock); } void* fun3(void *arg){ pthread_rwlock_wrlock(&rwlock); printf("This is fun3, wlock\n"); pthread_rwlock_unlock(&rwlock); } int main(void){ pthread_t tid1, tid2[5], tid3[5]; pthread_create(&tid1, NULL, fun1, NULL); sleep(1); int i; for(i = 0; i < 5; i++){ pthread_create(&tid2[i], NULL, fun2, NULL); //读锁 } for(i = 0; i < 5; i++){ pthread_create(&tid3[i], NULL, fun3, NULL); //写锁 } pthread_join(tid1, NULL); for(i = 0; i < 5; i++){ pthread_join(tid2[i], NULL); pthread_join(tid3[i], NULL); } return 0; }
运行结果
3、实现写锁优先
因为系统内部是写锁优先,经查看源码,现在实现此功能;以下是要实现的.c文件。
代码如下:
(1)、utili.h
#include<unistd.h> #include<stdio.h> #include<pthread.h>
(2)、pthread_rwlock.h
#ifndef _PTHREAD_RWLOCK_H #define _PTHREAD_RWLOCK_H #include"utili.h" enum {EINVAL, EBUSY}; 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; //<0 ==0 >0 }my_pthread_rwlock_t; #define RW_MAGIC 0x2016911 #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 *at); 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); #endif
(3)、pthread_rwlock_init.c
#include"pthread_rwlock.h" int my_pthread_rwlock_init(my_pthread_rwlock_t *rw, my_pthread_rwlockattr_t *at){ int result; if(at != 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; rw->rw_magic = RW_MAGIC; return 0; err3: pthread_cond_destroy(&rw->rw_condreaders); err2: pthread_mutex_destroy(&rw->rw_mutex); err1: return result; }
(4)、pthread_rwlock_wrlock.c
#include"pthread_rwlock.h" 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; }
(5)、pthread_rwlock_rdlock.c
#include"pthread_rwlock.h" 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) 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; } if(result == 0){ rw->rw_refcount++; } pthread_mutex_unlock(&rw->rw_mutex); return result; }
(6)、pthread_rwlock_unlock.c
#include"pthread_rwlock.h" 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("refcount error.\n"); } 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; }
(7)、pthread_rwlock_destroy.c
#include"pthread_rwlock.h" 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; }
(8)、test.c
#include"utili.h" #include"pthread_rwlock.h" my_pthread_rwlock_t rwlock = MY_PTHREAD_RWLOCK_INITIALIZER; void* fun1(void *arg){ my_pthread_rwlock_wrlock(&rwlock); printf("This is fun1. wrlock\n"); sleep(5); printf("fun1 wake up.\n"); my_pthread_rwlock_unlock(&rwlock); } void* fun2(void *arg){ my_pthread_rwlock_rdlock(&rwlock); printf("This is fun2.rdlock.\n"); my_pthread_rwlock_unlock(&rwlock); } void* fun3(void *arg){ my_pthread_rwlock_wrlock(&rwlock); printf("This is fun3,wrlock.\n"); my_pthread_rwlock_unlock(&rwlock); } int main(){ pthread_t tid1, tid2[5],tid3[5]; int i; pthread_create(&tid1, NULL, fun1, NULL); sleep(1); for(i=0; i<5; ++i){ pthread_create(&tid2[i], NULL, fun2, NULL); } for(i=0; i<5; ++i){ pthread_create(&tid3[i], NULL, fun3, NULL); } pthread_join(tid1, NULL); for(i=0; i<5; ++i){ pthread_join(tid2[i], NULL); pthread_join(tid3[i], NULL); } return 0; }
(9)、Makefile
OBJ=test.o pthread_rwlock_rdlock.o pthread_rwlock_unlock.o pthread_rwlock_wrlock.o pthread_rwlock_init .o SRC=test.c pthread_rwlock_rdlock.c pthread_rwlock_unlock.c pthread_rwlock_wrlock.c pthread_rwlock_init .c test:$(OBJ) gcc -o test $(OBJ) -lpthread test.o:test.c gcc -o test.o -c test.c pthread_rwlock_rdlock.o:pthread_rwlock_rdlock.c gcc -o pthread_rwlock_rdlock.o -c pthread_rwlock_rdlock.c pthread_rwlock_unlock.o:pthread_rwlock_unlock.c gcc -o pthread_rwlock_unlock.o -c pthread_rwlock_unlock.c pthread_rwlock_wrlock.o:pthread_rwlock_wrlock.c gcc -o pthread_rwlock_wrlock.o -c pthread_rwlock_wrlock.c pthread_rwlock_init.o:pthread_rwlock_init.c gcc -o pthread_rwlock_init.o -c pthread_rwlock_init.c .PHONY:clean clean: rm *.o test
运行结果:
这样我们自己就实现了写锁优先了,根据其原理,我们就可以改写为读锁优先。
本文出自 “11586096” 博客,请务必保留此出处http://11596096.blog.51cto.com/11586096/1855582
以上是关于读写锁的主要内容,如果未能解决你的问题,请参考以下文章