1、读写锁
互斥锁:试图进入临界区的所有其他进程都阻塞住。
读写锁:获取读写锁用于读和获取读写锁用于写作区分。
读写锁分配规则:
(1)、读锁:共享锁,此时可以有多个读锁,但是没有写锁。
(2)、写锁:独占锁,此时在也没有任何的写/读锁。
(3)、读写锁中,写锁优先抢占资源。
2、编程实现
需要使用:pthread_rwlock_t rwlock //定义了一个读写锁变量;
使用的API为:
函数 | 说明 |
pthread_rwlock_wrlock() | 写锁 |
pthread_rwlock_rdlock() | 读锁 |
pthread_rwlock_unlock() | 解锁 |
代码实现:
#include#include #include #include #include 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#include #include
(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.oSRC=test.c pthread_rwlock_rdlock.c pthread_rwlock_unlock.c pthread_rwlock_wrlock.c pthread_rwlock_init.ctest:$(OBJ) gcc -o test $(OBJ) -lpthreadtest.o:test.c gcc -o test.o -c test.cpthread_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.cpthread_rwlock_wrlock.o:pthread_rwlock_wrlock.c gcc -o pthread_rwlock_wrlock.o -c pthread_rwlock_wrlock.cpthread_rwlock_init.o:pthread_rwlock_init.c gcc -o pthread_rwlock_init.o -c pthread_rwlock_init.c.PHONY:cleanclean: rm *.o test
运行结果:
这样我们自己就实现了写锁优先了,根据其原理,我们就可以改写为读锁优先。