C实现读写锁


一、概述

  案例:编写一个案例测试读写锁,要求:新建三个线程写,5个线程读,来测试读写锁。

  读写锁的基本概念:

      读写锁也叫共享-独占锁。当读写锁以读模式锁住时,它是以共享模式锁住的;当它以写模式锁住时,它是以独占模式锁住的。写独占,读共享

  读写锁的使用场合:

      对数据结构读的次数远大于写的情况

  读写锁的特性:

      1.读写锁是“写模式加锁”时,解锁前,所有对该锁加锁的线程都会被阻塞

      2.读写锁是“读模式加锁”时,如果线程以读模式对其加锁会成功;如果线程以写模式加锁会阻塞。

      3.读写锁是“读模式加锁”时, 既有试图以写模式加锁的线程,也有试图以读模式加锁的线程。那么读写锁会阻塞随后的读模式锁请求。优先满足写模式锁。读锁、写锁并行阻塞,写锁优先级高

  读写锁场景练习:

    1. 线程A加写锁成功, 线程B请求读锁

    答:线程B阻塞

    2.线程A持有读锁, 线程B请求写锁

    答:线程B阻塞

    3.线程A拥有读锁, 线程B请求读锁

    答:线程B加锁成功

    4.线程A持有读锁, 然后线程B请求写锁, 然后线程C请求读锁

    答:B阻塞,c阻塞 - 写的优先级高

    5.A解锁,B线程加写锁成功,C继续阻塞

    答:B解锁,C加读锁成功

    6.线程A持有写锁, 然后线程B请求读锁, 然后线程C请求写锁

    答:BC阻塞

    7.A解锁,C加写锁成功,B继续阻塞

    答:C解锁,B加读锁成功

  读写锁操作的基本步骤:

    1.定义一把锁:pthread_rwlock_t rwlock;

    2.初始化读写锁:pthread_rwlock_init()

    3.加读锁:pthread_rwlock_rdlock()

    4.加写锁:pthread_rwlock_wrlock()

    5.解锁:pthread_rwlock_unlock();

    6.释放锁:pthread_rwlock_destroy();

  根据以上6步骤,下面看看具体的代码示例

二、代码示例

//读写锁测试程序
#include 
#include 
#include <string.h>
#include 
#include 
#include 

//定义一个全局变量
int number = 0;
//定义一把读写锁
pthread_rwlock_t rwlock;


//写线程回调函数
void * thread_write(void *arg){
        int i = *(int *)arg;
        int cur;
        while(1){
                //加写锁
                pthread_rwlock_wrlock(&rwlock);
                cur = number;
                cur++;
                number = cur;
                printf("[%d]-W:[%d]\n",i,cur);
                //解锁
                pthread_rwlock_unlock(&rwlock);
                sleep(rand()%3);
        }
}

//读线程回调函数
void *thread_read(void *arg){
        int i = *(int *)arg;
        int cur;
        while(1){
                //加读锁
                pthread_rwlock_rdlock(&rwlock);
                cur = number;
                printf("[%d]-R:[%d]\n",i,cur);
//读写锁测试程序
#include 
#include 
#include <string.h>
#include 
#include 
#include 

//定义一个全局变量
int number = 0;
//定义一把读写锁
pthread_rwlock_t rwlock;


//写线程回调函数
void * thread_write(void *arg){
        int i = *(int *)arg;
        int cur;
        while(1){
                //加写锁
                pthread_rwlock_wrlock(&rwlock);
                cur = number;
                cur++;
                number = cur;
                printf("[%d]-W:[%d]\n",i,cur);
                //解锁
                pthread_rwlock_unlock(&rwlock);
                sleep(rand()%3);
        }
}

//读线程回调函数
void *thread_read(void *arg){
        int i = *(int *)arg;
        int cur;
        while(1){
                //加读锁
                pthread_rwlock_rdlock(&rwlock);
                cur = number;
                printf("[%d]-R:[%d]\n",i,cur);
                //解锁
                pthread_rwlock_unlock(&rwlock);
                sleep(rand()%3);
        }

}

int main(){
        int n = 8;
        int i =0;
        int arr[8];
        //定义线程 id
        pthread_t thread[8];
        //初始化读写锁
        pthread_rwlock_init(&rwlock,NULL);
        //创建是哪个写锁
        for(i=0;i<3;i++){
                arr[i] = i;
                //创建写线程
                pthread_create(&thread[i],NULL,thread_write,&arr[i]);
        }
        //创建5个读线程
        for(i=3;i){
                arr[i] = i;
                //创建读线程
                pthread_create(&thread[i],NULL,thread_read,&arr[i]);
        }
        //回收子线程
        int j = 0;
        for(j=0;j){
                pthread_join(thread[j],NULL);
        }
        //释放锁
        pthread_rwlock_destroy(&rwlock);
        return 0;
}
    

三、示例图

  如下图所示:读出来的数据永远是写入的最后一个数据。