【Linux】读者写者模型

前面我们已经学过了生产者消费者模型,那本文就来介绍一个与它有些相似却又不同的读者写者模型。

什么是读者写者模型?

  一个数据文件或记录可以被多个进程共享,我们把只要求读文件的进程称为Reader进程,其他进程则被称为Write进程。允许多个进程同时读一个共享对象,但是不允许一个Write进程和其他Reader进程或Writer进程同时访问对象。因为这样可能会造成混乱。所谓“读者写者问题”只是保证一个Writer进程必须与其他进程互斥地访问共享对象的同步问题。
  
总结一下,也是”321“原则:
三种关系
(1)写者与写者:不能两个人同时写,所以互斥
(2)读者与读者:可以两个人同时读,所以没有关系,也可以说是共享的
(3)写者与读者:一个文件不能又是被读,又是被写的,所以互斥;写完了才能读,不读了才开始写,所以说又是同步的。
两种角色:读者和写者。
一个读写场所。

读者写者模型的“321”原则,虽然与生产者消费者很类似,但是却又不同。消费者是将数据带拿走,而读者则只是读数据,数据还在,并没有被拿走。这是两者之间最大的不同。

读写锁

  有时候经常会出现公共资源修改的机会比较少,读资源的机会比较多的情况,此时,就需要用到我们的读写锁了。读写锁是一种特殊的自旋锁,能提高并发性。它允许多个多个读者来访问资源;写者是排他性的,一个读写锁同时只能有一个写者或多个读者,但不能同时既有读者又有写者。
  如果读写锁当前没有读者,也没有写者,那么写者可以立刻获得读写锁,否则它必须自旋在那,直到没有任何写者或读者;反过来,如果读写锁没有写者,那么读者就可以立刻得到读写锁,否则,它要自旋知道写者释放读写锁。

自旋锁

  自旋锁与互斥锁比较类似,都是为了解决资源的互斥问题。对于互斥锁来说,如果资源已经被占用,申请者只能挂起等待,直到被唤醒。自旋锁则不会被挂起,它会一直循环着看锁是否被释放。
  自旋锁适用于占用临界资源时间较短的时候,因为自旋锁不会引起调用者睡眠,所以自旋锁的效率高于互斥锁。但是由于自旋锁一直占用CPU,所以如果不能在短时间内获得锁,谁使用CPU效率下降。

注意:写独占,读共享,写锁的优先级高

读写锁的接口

初始化:

 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, 
                const pthread_rwlockattr_t *restrict attr);

销毁:

 int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

加锁:

 int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);//写锁
 int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);//读锁

解锁:

 int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

下面我们写代码来使用一下读写锁,以加深印象。
这里使用线程来操作,创建三个写的线程,五个读的线程,这里写者优先级高。

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
pthread_rwlock_t rwlock;
int count = 0;

void* route_write(void* arg)
{
    int i = (int)arg;
    int t = 0;
    while(1)
    {
        t = count;
        usleep(10000);
        pthread_rwlock_wrlock(&rwlock);
        printf("(write)no:(%d), id=%x, t=%d, count=%d\n", i, pthread_self(), t, ++count);
        pthread_rwlock_unlock(&rwlock);
        usleep(90000);
    }
}

void* route_read(void* arg)
{
    int i = (int)arg;
    while(1)
    {
        pthread_rwlock_rdlock(&rwlock);
        printf("(read)no:(%d), id=%x, count=%d\n", i, pthread_self(), count);
        pthread_rwlock_unlock(&rwlock);
        usleep(10000);
    }
}
int main()
{
    pthread_t tid[8];
    pthread_rwlock_init(&rwlock, NULL);
    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;
}

运行结果:可以发现读者出现的比较多,写者出现的比较少。
这里写图片描述
这里写图片描述

猜你喜欢

转载自blog.csdn.net/wei_cheng18/article/details/79954634