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
运行结果:
这样我们自己就实现了写锁优先了,根据其原理,我们就可以改写为读锁优先。
转载于:https://blog.51cto.com/wait0804/1855582