读写锁

  • 在编写多线程时,有一种情况很常见,那就是,有些公共数据修改的机会比较少,相比较改写,它们读得机会反而高得多。通常而言,在读的过程中,往往伴随着查找的操作,中间耗时较长。给这种代码段加锁,会极大地降低我们程序的效率。读写锁就是专门处理这种多读少写的情况的。
  • 读写锁本质上是一种自旋锁。何谓自旋锁?它是为实现保护共享资源而提出一种锁机制。其实,自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名。
  • 举个例子来说,当我们需要长时间去等一个人的时候,我们通常采取的措施是先去做其他事情,当要等的人处理完自己的事情时,再来通知等待者。而在短时间内去等一个人时,我们就不会再去做其他事情,而是在原地等待,并且在等待期间时不时地询问要等的人还需要多久。这两种情况就正好对应了挂起等待锁和自旋锁。当预计线程等待的时间很短时,一般会采用自旋锁;当预计等待的线程时间很长时,一般会使用挂起等待锁。
  • 读写锁的行为:

  • 读写锁接口:
1、初始化

函数原型:int   pthread_rwlock_init(pthread_rwlock_t   *restrict   rwlock,const   pthread_rwlockattr_t   *restrict   attr);

2、销毁:

函数原型:int   pthread_rwlock_destroy(pthread_rwlock_t   *rwlock);

3、加锁:

(1)加读锁:

函数原型:int   pthread_rwlock_rdlock(pthread_rwlock_t   *rwlock);

(2)加写锁:

函数原型:int   pthread_rwlock_wrlock(pthread_rwlock_t   *rwlock);

4、解锁:

函数原型:int   pthread_rwlock_unlock(pthread_rwlock_t   *rwlock);

  • 读写锁实例:
#include <stdio.h>
#include<pthread.h>

pthread_rwlock_t rwlock;
int count = 0;

void *route_write(void *arg){
    int no = (int)arg;
    while(1){
        int t = count;
        usleep(50000);
        pthread_rwlock_wrlock(&rwlock);
        printf("(writer)thread(%d)id:%x,inc %d to %d\n",no,pthread_self(),t,++count);
        pthread_rwlock_unlock(&rwlock);
        usleep(1000000);
    }
}

void *route_read(void *arg){
    int no = (int)arg;
    while(1){
        pthread_rwlock_rdlock(&rwlock);
        printf("(reader)thread(%d)id:%x,data:%d\n",no,pthread_self(),count);
        pthread_rwlock_unlock(&rwlock);
        usleep(20000);
    }
}

int main(){
    pthread_rwlock_init(&rwlock,NULL);
    pthread_t tid[8];
    int i = 0;
    for(;i<3;i++){
        pthread_create(tid+i,NULL,route_write,(void*)i);
    }
    for(i=3;i<8;i++){
        pthread_create(tid+i,NULL,route_read,(void*)i);
    }
    for(i=0;i<8;i++){
        pthread_join(tid[i],NULL);
    }
    pthread_rwlock_destroy(&rwlock);
    return 0;
}

结果演示:


  • 读者写者模型:
1、三个关系:

(1)读者与读者之间:共享关系;

(2)读者与写者之间:互斥且同步;

(3)写者与写者之间:互斥。

2、读者写者模型与生产者消费者模型的区别:

(1)生产者消费者模型中消费者会拿走数据;但在读者写者模型中,读者不会拿走数据。

(2)在生产者消费者模型中,消费者与消费者之间是互斥关系;但在读者写者模型中,读者与读者之间共享资源。

3、读者优先:

(1)读者、写者互斥访问文件资源;

(2)多个读者可以同时访问文件资源;

(3)只允许一个写者。

4、写者优先:

(1)写者线程的优先级高于读者线程;

(2)当没有写者到来时应该阻塞读者线程的队列;

(3)当有一个写者正在写时或在阻塞队列中时,应该阻塞读者线程的读操作,直到所有的写者线程完成写操作时,即可对读者线程解除阻塞;

(4)当没有写者线程时,读者线程应该能够同时读取文件。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值