读写锁

1、读写锁

  互斥锁:试图进入临界区的所有其他进程都阻塞住。

  读写锁:获取读写锁用于读和获取读写锁用于写作区分。

  读写锁分配规则:

  (1)、读锁:共享锁,此时可以有多个读锁,但是没有写锁。

  (2)、写锁:独占锁,此时在也没有任何的写/读锁。

  (3)、读写锁中,写锁优先抢占资源。

2、编程实现

  需要使用:pthread_rwlock_t  rwlock  //定义了一个读写锁变量;

  使用的API为:

函数
说明
pthread_rwlock_wrlock()
写锁
pthread_rwlock_rdlock()
读锁
pthread_rwlock_unlock()解锁

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#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;
}

运行结果

wKiom1fjwwHi0kbLAABzWxEYtKQ839.png-wh_50

3、实现写锁优先

  因为系统内部是写锁优先,经查看源码,现在实现此功能;以下是要实现的.c文件。

wKiom1fjyQzSvjN_AABQz3mTXv4737.png-wh_50

  代码如下:

(1)、utili.h

1
2
3
#include<unistd.h>
#include<stdio.h>
#include<pthread.h>

(2)、pthread_rwlock.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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

运行结果:

wKiom1fjznjDc-I7AADtFdk4upc141.png-wh_50

这样我们自己就实现了写锁优先了,根据其原理,我们就可以改写为读锁优先。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值