1、问题:在操作系统内对线程是写锁优先,如何实现读锁优先呢?
分析:的利用互斥量和条件变量来进行实现,由于已经对操作系统的写锁优先进行了实现,那么对其原理应该已经掌握了,直接代码实现。
代码如下:
(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;void reader_clean_up(void *arg);void writer_clean_up(void *arg);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_nwaitreaders>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) while(rw->rw_refcount < 0){ rw->rw_nwaitreaders++; //pthread_cleanup_push(reader_clean_up); result = pthread_cond_wait(&rw->rw_condreaders, &rw->rw_mutex); //pthread_cleanup_pop(0); rw->rw_nwaitreaders--; if(result != 0){ break; } } if(result == 0){ rw->rw_refcount++; } pthread_mutex_unlock(&rw->rw_mutex); return result;}
(6)、pthread_rwlock_trywrlock.c
#include"utili.h"#include"pthread_rwlock.h"int pthread_rwlock_trywrlock(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){ result = EBUSY; }else{ rw->rw_refcount = -1; } pthread_mutex_unlock(&rw->rw_mutex); return result;}
(7)、pthread_rwlock_tryrdlock.c
#include"utili.h"#include"pthread_rwlock.h"int pthread_rwlock_tryrdlock(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_nwaitwriters > 0){ result = EBUSY; }else{ rw->rw_refcount++; } pthread_mutex_unlock(&rw->rw_mutex); return result;}
(8)、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_nwaitreaders > 0){ result = pthread_cond_broadcast(&rw->rw_condreaders); }else if(rw->rw_nwaitwriters > 0){ if(rw->rw_refcount == 0) result = pthread_cond_signal(&rw->rw_condwriters); } //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;}
(9)、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;}
(10)、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;}
(11)、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.c -gpthread_rwlock_rdlock.o:pthread_rwlock_rdlock.c gcc -o pthread_rwlock_rdlock.o -c pthread_rwlock_rdlock.c -gpthread_rwlock_unlock.o:pthread_rwlock_unlock.c gcc -o pthread_rwlock_unlock.o -c pthread_rwlock_unlock.c -gpthread_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
运行结果
此时已经实现了读锁优先(只要对写锁优先熟悉,稍作更改就可以了)。