• linux读写锁


    读写锁的认识

    (1)读写锁是一把锁
    (2)读写锁的类型: pthread_rwlock_t lock 又分“读锁”(对内存进行读操作)和“写锁”(对内存进行写操作)
    (3)读写锁的特性:
    1)读共享-并行处理:例如,线程 A 加读锁成功,有来个 3 个线程,作读操作,也可加锁成功。
    2)写独占-串行处理:例如,线程 A 加写锁成功,有来个 3 个线程,作读操作,3 个线程阻塞。
    3) 读写不能同时进行,写的优先级高:例如,线程A加读锁成功,又来了B线程加写锁阻塞,又来了C线程加读锁阻塞
    (4)读写锁的场景练习:
    1)线程 A 加写锁成功,线程 B 请求读锁 :B 读阻塞。
    2)线程 A 加读锁成功,线程 B 请求写锁 :B 写阻塞。
    3)线程 A 加读锁成功,线程 B 请求读锁 :线程 B 加读锁成功。
    4)线程 A 加读锁成功,然后线程 B 请求写锁,然后线程 C 请求读锁 :B 写阻塞,C 读阻塞;
    A 解锁 :B 加写锁成功,C 继续读阻塞 ;
    B 解锁 :C 加读锁成功。
    5)线程 A 加读写成功,然后线程 B 请求读锁,然后线程 C 请求写锁 :B 读阻塞,C 写阻塞;
    A 解锁 :C 加写锁成功,B 继续读阻塞;
    C 解锁 :B 加读锁成功。
    (5)读写锁与互斥锁的区别
    互斥锁 : 读写串行 。
    读写锁 : 读并行,写串行。
    读写锁更关注“读并行”,如果关注串行,那直接用互斥锁好了,所以读写锁更适用于读操作多的场景,通过其并行的特性,可以提高效率。

    读写锁的相关函数

    初始化读写锁

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

    销毁读写锁

    pthread_rwlock_destroy(pthread_rwlock_t* rwlock):
    
    • 1

    加读锁

    pthread_rwlock_rdlock(pthread_rwlock_t* rdlock);
    
    • 1

    阻塞:之前对这把锁加的是写锁的操作
    尝试加读锁

    pthread_rwlock_tryrdlock(pthread_rwlock_t* rwlock);
    
    • 1

    加锁成功:返回0
    失败:返回错误号
    加写锁

    pthread_rwlock_wrlock(pthread_rwlock_t* rwlock);
    
    • 1

    阻塞:上一次加写锁还没解锁
    阻塞:上一次加读锁还没解锁
    尝试加写锁

    pthread_rwlock_trywrlock(pthread_rwlock_t* rwlock);
    
    • 1

    解锁

    pthread_rwlock_unlock(pthread_rwlock_t* rwlock)
    
    • 1

    练习

    三个线程不定时写同一个全局变量,五个线程不定时期读同一全局资源
    先不加锁:

    #include 
    #include 
    #include 
    
    int number=0;
    pthread_rwlock_t rwlock;
    void *write_pthread(void * arg)
    {
            while(1)
            {
                    //pthread_rwlock_wrlock(&rwlock);
                    number++;
                    printf("write_pthread id:%ld, number is %d\n",pthread_self(),number);
                    usleep(500);
                    //pthread_rwlock_unlock(&rwlock);
            }
    }
    void *read_pthread(void * arg)
    {
            while(1)
            {
                    //pthread_rwlock_wrlock(&rwlock);
                    printf("read_pthread id: %ld,number is %d\n",pthread_self(),number);
                    usleep(500);
                    //pthread_rwlock_unlock(&rwlock);
            }
    }
    
    int main()
    {
            pthread_t p[8];
            pthread_rwlock_init(&rwlock,NULL);
            for(int i=0;i<3;i++)
            {
                    pthread_create(&p[i],NULL,write_pthread,NULL);
            }
            for(int i=3;i<8;i++)
            {
                    pthread_create(&p[i],NULL,read_pthread,NULL);
            }
            for(int j=0;j<8;j++)
            {
                    pthread_join(p[j],NULL);
            }
            return 0;
    }
    
    
    • 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

    截取结果片段:
    请添加图片描述
    发现读的number值有时会小于写的number值,这因为没加读写锁时,读和写线程都是并发执行,会引发混乱。

    加读写锁:

    #include 
    #include 
    #include 
    
    int number=0;
    pthread_rwlock_t rwlock;
    void *write_pthread(void * arg)
    {
            while(1)
            {       //加写锁
                    pthread_rwlock_wrlock(&rwlock);
                    number++;
                    printf("write_pthread id:%ld, number is %d\n",pthread_self(),number);
                    pthread_rwlock_unlock(&rwlock);
                    //解锁
                    sleep(1);
            }
    }
    void *read_pthread(void * arg)
    {
            while(1)
            {       //加读锁
                    pthread_rwlock_wrlock(&rwlock);
                    printf("read_pthread id: %ld,number is %d\n",pthread_self(),number);
                    pthread_rwlock_unlock(&rwlock);
                    //解锁
                   sleep(1);
            }
    }
    
    int main()
    {
            pthread_t p[8];
            pthread_rwlock_init(&rwlock,NULL);
            for(int i=0;i<3;i++)
            {
                    pthread_create(&p[i],NULL,write_pthread,NULL);
            }
            for(int i=3;i<8;i++)
            {
                    pthread_create(&p[i],NULL,read_pthread,NULL);
                     }
            for(int j=0;j<8;j++)
            {
                    pthread_join(p[j],NULL);
            }
            return 0;
    }
    
    • 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

    执行结果:
    请添加图片描述
    可以看到加了读写锁以后,读是并行的,写串行的,number的顺序是由小到大,不会发生混乱。

  • 相关阅读:
    短信验证码
    Orange3数据可视化组件概览
    FreeSWITCH 1.10.10 简单图形化界面12 - 注册IMS
    数字化底层逻辑揭秘!探寻地产工程行业发展新范式
    【Akka】Akka 学习 akka 两本书的读后感
    将DataFrame中符合指定条件的数据替换为指定的值:mask()函数
    微信小程序自动化测试pytest版工具使用方法
    telnet 连接闪退
    Python制作AI贪吃蛇,很多很多细节、思路都写下来了!
    详解GaussDB(DWS)中的行执行引擎
  • 原文地址:https://blog.csdn.net/m0_57678852/article/details/127945050