• linux-读写锁(rwlock)


    概述

            读写锁与互斥量类似,不过读写锁允许更改的并行性,也叫共享互斥锁 。互斥量要么是锁住状态,要么就是不加锁状态,而且一次只有一个线程可以对其加锁。读写锁可以有 3 种状态:读模式下加锁状态、写模式加锁状态、不加锁状态
            一次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时占有读模式 的读写锁(允许多个线程读但只允许一个线程写)

    读写锁的特点

    1.如果有其它线程读数据,则允许其它线程执行读操作,但不允许写操作;
    2.如果有其它线程写数据,则其它线程都不允许读、写操作
    3 如果某线程申请了读锁,其它线程可以再申请读锁,但不能申请写锁;
    4.如果某线程申请了写锁,其它线程不能申请读锁,也不能申请写锁。
    读写锁适合于对数据结构的 读次数比写次数多得多 的情况。

    读写锁定义

    在 linux 中,通过 pthread_rwlock_t 结构来表示一个读写锁

    typedef union
    {
            struct __pthread_rwlock_arch_t __data ;
            char __size [ __SIZEOF_PTHREAD_RWLOCK_T ];
            long int __align ;
    } pthread_rwlock_t ;
    对于读写锁的操作有:
    1.初始化读写锁
    2.销毁读写锁
    3.获取读锁
    4.获取写锁
    5.解锁

    初始化读写锁

    动态初始化(pthread_rwlock_init)

    头文件:
    #include 
    函数原型:
    int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restrict attr);
    作用:
            初始化读写锁 rwlock
    参数含义:
            rwlock:读写锁
            attr:读写锁的属性,为 NULL 表示默认属性
    返回值:
            成功返回 0
            失败返回其他值

    静态初始化

            在 linux 中使用静态存储区的 PTHREAD_RWLOCK_INITIALIZER 就可以完成对读写锁的初
    始化工作。
    # define PTHREAD_RWLOCK_INITIALIZER \
    { { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , __PTHREAD_RWLOCK_ELISION_EXTRA , 0 ,
    0 } }

    静态初始化方式如下:

    pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
            动态初始化是在堆中申请空间,需要释放,而静态初始化是在静态存储区中创建,不
    需要释放。

    释放读写锁(pthread_rwlock_destroy)

    头文件:
    #include 
    函数原型:
    int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
    作用:
            释放读写锁 rwlock
    参数含义:
            rwlock:读写锁
    返回值:
            成功返回 0
            失败返回其他值

    申请读锁

    阻塞方式(pthread_rwlock_rdlock)

    头文件:
    #include 
    函数原型:
    int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
    作用:
            申请读锁 rwlock ,阻塞申请
    参数含义:
            rwlock:读写锁
    返回值:
            成功返回 0
            失败返回其他值

    非阻塞方式(pthread_rwlock_tryrdlock)

    头文件:
    #include 
    函数原型:
    int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
    作用:
            申请读锁 rwlock ,非阻塞申请
    参数含义:
            rwlock:读写锁
    返回值:
            成功返回 0 (不管申请是否成功都会返回 0,除非锁不存在或其他异常情况)
            失败返回其他值

    申请写锁

    阻塞方式(pthread_wrlock_wrlock)

    头文件:
    #include 
    函数原型:
    int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
    作用:
            申请写锁 rwlock , 阻塞等待
    参数含义:
            rwlock:读写锁
    返回值:
            成功返回 0
            失败返回其他值

    非阻塞方式(pthread_rwlock_trywrlock)

    头文件:
    #include 
    函数原型:
    int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
    作用:
            申请写锁 rwlock ,非阻塞申请
    参数含义:
            rwlock:读写锁
    返回值:
            成功返回 0 (不管申请是否成功都会返回 0,除非锁不存在或其他异常情况)
            失败返回其他值

    解锁

    头文件:
    #include 
    函数原型:
    int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
    作用:
            释放读写锁资源( 解锁 )
    参数含义:
             rwlock: 读写锁
    返回值:
            成功返回 0
            失败返回其他值

    简单使用实例

    1. // 一个使用读写锁来实现 4 个线程读写一段数据是实例。
    2. // 在此示例程序中,共创建了 4 个线程,
    3. // 其中两个线程用来写入数据,两个线程用来读取数据
    4. #include
    5. #include
    6. #include
    7. pthread_rwlock_t rwlock; //读写锁
    8. int num = 1;
    9. //读操作,其他线程允许读操作,却不允许写操作
    10. void *fun1(void *arg)
    11. {
    12. while(1)
    13. {
    14. pthread_rwlock_rdlock(&rwlock);
    15. printf("read num first == %d\n", num);
    16. pthread_rwlock_unlock(&rwlock);
    17. sleep(1);
    18. }
    19. }
    20. //读操作,其他线程允许读操作,却不允许写操作
    21. void *fun2(void *arg)
    22. {
    23. while(1)
    24. {
    25. pthread_rwlock_rdlock(&rwlock);
    26. printf("read num second == %d\n", num);
    27. pthread_rwlock_unlock(&rwlock);
    28. sleep(2);
    29. }
    30. }
    31. //写操作,其它线程都不允许读或写操作
    32. void *fun3(void *arg)
    33. {
    34. while(1)
    35. {
    36. pthread_rwlock_wrlock(&rwlock);
    37. num++;
    38. printf("write thread first\n");
    39. pthread_rwlock_unlock(&rwlock);
    40. sleep(2);
    41. }
    42. }
    43. //写操作,其它线程都不允许读或写操作
    44. void *fun4(void *arg)
    45. {
    46. while(1)
    47. {
    48. pthread_rwlock_wrlock(&rwlock);
    49. num++;
    50. printf("write thread second\n");
    51. pthread_rwlock_unlock(&rwlock);
    52. sleep(1);
    53. }
    54. }
    55. int main()
    56. {
    57. pthread_t ptd1, ptd2, ptd3, ptd4;
    58. pthread_rwlock_init(&rwlock, NULL);//初始化一个读写锁
    59. //创建线程
    60. pthread_create(&ptd1, NULL, fun1, NULL);
    61. pthread_create(&ptd2, NULL, fun2, NULL);
    62. pthread_create(&ptd3, NULL, fun3, NULL);
    63. pthread_create(&ptd4, NULL, fun4, NULL);
    64. //等待线程结束,回收其资源
    65. pthread_join(ptd1, NULL);
    66. pthread_join(ptd2, NULL);
    67. pthread_join(ptd3, NULL);
    68. pthread_join(ptd4, NULL);
    69. pthread_rwlock_destroy(&rwlock);//销毁读写锁
    70. return 0;
    71. }

  • 相关阅读:
    一个简单的HTML篮球网页【学生网页设计作业源码】
    环信uni-app-demo 升级改造计划——单人&多人音视频通话(三)
    致敬最美逆行者网页设计作品 大学生抗疫感动专题网页设计作业模板 疫情感动人物静态HTML网页模板下载
    Spring-依赖注入
    centos安装flink,通过windows访问webui
    Linux基础内容(12)—— 程序地址空间
    Elasticsearch:自定义应用程序的日志记录 - Elastic Common Schema
    Python time模块获得当前时间
    什么是MapReduce?MapReduce整体架构搭建使用介绍
    【云原生 | 42】Docker快速部署高可靠性编程语言Erlang
  • 原文地址:https://blog.csdn.net/jiu_yue_ya/article/details/132802761