• 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. }

  • 相关阅读:
    【SysBench】Linux 安装 sysbench-1.20
    Redis数据类型——set类型数据介绍及操作
    threadSafeMap代码解析
    【vue.js】路由使用与Node.js下载安装之环境配置
    npm、cnpm、pnpm使用详细
    Nginx(四) absolute_redirect、server_name_in_redirect、port_in_redirect 请求重定向指令组合测试
    黑客技术之远程关机
    云计算HCIA学习笔记-云计算基础概念
    redis之单线程的redis都有哪些阻塞点
    千帆竞发-Redis分布式锁
  • 原文地址:https://blog.csdn.net/jiu_yue_ya/article/details/132802761