用读写锁实现--读者写者模型

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ZWE7616175/article/details/79945194

读者写者模型

读者写者模型是操作系统中的一种同步与互斥机制,与生产者消费者模型类似,但不同的是在生产者消费者模型中,多个读者间没有关系,而且消费者会让临界资源的个数减少,而读者不会改变临界资源的个数
这里写图片描述

读者写者模型应该具备的条件

1.写者是排他性的,即有多个写者的情况下,只有一个写者占有仓库。
2.读者可以一起读,采取并行机制。
3.读者和写者是同步且互斥的,如果读者占有了仓库,则写者不能占有,若写者正在写,则读者不能访问仓库。

读者写者模型的策略

1.读者优先
读者先来读取数据,此时写者处于阻塞状态,当读者读取完数据后且没有了读者时写者才能访问仓库。
2.写者优先
写者先写入数据,此时读者处于阻塞状态,当写者写完数据后且没有写者时读者才能访问仓库。
3.公平情况
写者和读者访问仓库的优先级相等,谁先进入优先级队列谁先访问。

自旋锁与挂起等待锁

1.自旋锁
线程申请资源失败时,它会一直在当前检测锁位置处轮寻锁的状态,来查看资源是否能被申请。不断检测的过程叫做自旋,如读写锁。
2.挂起等待锁
线程申请资源失败时,操作系统将其挂起等待,如互斥锁和二元信号量。

读写锁

什么是读写锁?
读写锁是一种特殊的自旋锁,它把对共享资源的访问者划分为读者和写者,读者只对共享资源进行读访问,写者需对贡献资源进行写操作,这个锁相对于自旋锁而言,能提高并发性。原因是在多处理器系统中,允许同时有多个读者来访问共享资源,最大的读者数量其实为实际的逻辑CPU数。写者是排他性的,一个读写锁可以同时有一个写者或多个读者,但不能同时既有读者又有写者。

读写锁的状态
1.写加锁状态
当处于写加锁状态,在被解锁之前,所有试图对锁进行访问的线程都会被阻塞,通俗来讲,就是“只有自己可以进行写,其他操作都不能进行”。
2.读加锁状态
当处于读加锁状态,所有试图以读模式对这个锁进行访问的线程都可以获得访问权,但是任何以写模式对锁进行访问的线程都会被阻塞,直到所有的线程都释放他们的读状态锁为止。通俗来讲,就是“只要线程是读模式就可以访问”。

读写锁相关函数
1.初始化读写锁&销毁
这里写图片描述
参数:
attr表示初始化读写锁的属性,NULL为默认属性。

2.读加锁函数
这里写图片描述
返回值:成功返回0,失败返回错误码。
注意:因为操作系统对读者数量有限制,所以当我们使用读加锁函数时最好先判断一下返回值。

3.写加锁函数
这里写图片描述
返回值:成功返回0,失败返回错误码。
pthread_rwlock_rdlock加锁失败则被挂起等待,pthread_rwlock_trylock加锁失败不挂起等待采用轮询式等待。

4.解锁函数
这里写图片描述
返回值:成功返回0,失败返回错误码。
对于读加锁和写加锁而言,解锁函数相同。

代码实现读者写者模型:
4个写者线程,6个读者线程。

#include <stdio.h>                           
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

int count;
pthread_rwlock_t rwlock;

//write
void *writer(void *arg){
    int t;
    int i = *(int*)arg;
    free(arg);

    while(1){
        t = count;
        usleep(10000);

        pthread_rwlock_wrlock(&rwlock);
        printf("write:%d:%#X:count=%d ++count=%d\n",i,pthread_self()\
                ,t,count++);
        pthread_rwlock_unlock(&rwlock);
        usleep(50000);
    }
}

//read
void *reader(void *arg){
    int t;
    int i = *(int*)arg;
    free(arg);

    while(1){
        pthread_rwlock_rdlock(&rwlock);
        printf("read:%d:%#X:count=%d\n",i,pthread_self(),count);
        pthread_rwlock_unlock(&rwlock);
        usleep(9000);
    }
}

int main()
{
    int i;
    pthread_t tid[10];
    pthread_rwlock_init(&rwlock, NULL);                                     

    for(i=0;i<4;++i){
        int *p = (int*)malloc(sizeof(int));
        *p = i;
        pthread_create(&tid[i], NULL, writer, (void*)p);
    }

    for(i=0;i<6;++i){
        int *p = (int*)malloc(sizeof(int));
        *p = i;
        pthread_create(&tid[i], NULL, reader, (void*)p);
    }

    for(i=0;i<10;++i){
        pthread_join(tid[i], NULL);
    }

    pthread_rwlock_destroy(&rwlock);

    return 0;
}

运行结果:
这里写图片描述

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页