Linux---线程读写锁详解及代码实现

简介: Linux---线程读写锁详解及代码实现

一、读写锁原理

在实际问题中,互斥锁可以解决大部分互斥的问题,保证资源可以被独占式使用,但是有时候互斥锁可能会导致效率降低。比如:系统中有成千上万条线程对同一资源进行访问,其中绝大部分是对其进行读取,只有少部分线程需要对其进行写入,这样使用互斥锁效率就会很低,所以使用读写锁。

读锁:获取数据( read、printf、fread、fget、get、getchar、scanf),当一个线程上了读锁,其他线程可以一直上读锁。

写锁:修改数据(write、puts、fwrite、fputs、putchar)当一个线程上了写锁,后面的其他线程读、写都不能上,直到解了第一个写锁。


二、读写锁对对应的API

1、初始化读写锁

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

attr:锁的属性一般设置为NULL

返回值:成功返回0,失败返回非0

静态初始化读写锁: pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;

代码段:

 pthread_rwlock_t rwl;
 int pthread_rwlock_init_ret = pthread_rwlock_init(&rwl, NULL);
   if (pthread_rwlock_init_ret != 0)
   {
       perror("pthread_rwlock_init");
       exit(-1);
   }
   else
   {
       printf("读写锁初始化成功!\n");
   }

2、读锁、写锁、销毁读写锁

读锁:int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);

写锁:int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

销毁读写锁:int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

代码段:验证上了写锁后只有在解了写锁才能再上读锁

#include <stdio.h>
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
pthread_rwlock_t rwl;
void *Pthread_Task(void *arg)
{
    if ((long)arg == 1)
    {
        printf("我是第%ld号线程,我要上写锁\n", (long)arg);
        int pthread_rwlock_rdlock_ret = pthread_rwlock_wrlock(&rwl);
        if (pthread_rwlock_rdlock_ret != 0)
        {
            perror("pthread_rwlock_rdlock");
            exit(-1);
        }
        else
        {
            printf("我是%ld号线程,我上写锁成功!3s之后我解写锁\n", (long)arg);
            sleep(3);
            int pthread_rwlock_unlock_ret = pthread_rwlock_unlock(&rwl);
            if(pthread_rwlock_unlock_ret != 0)
            {
                perror("pthread_rwlock_unlock");
                exit(-1);
            }
            else
            {
                printf("解写锁成功!\n");
            }
        }
    }
    if ((long)arg == 2)
    {
        printf("我是第%ld号线程,我要上读锁\n", (long)arg);
        int pthread_rwlock_rdlock_ret = pthread_rwlock_rdlock(&rwl);
        if (pthread_rwlock_rdlock_ret != 0)
        {
            perror("pthread_rwlock_rdlock");
            exit(-1);
        }
        else
        {
            printf("我是%ld号线程,我上读锁成功!\n", (long)arg);
        }
    }
    pthread_exit(NULL);
}

int main()
{
    int pthread_rwlock_init_ret = pthread_rwlock_init(&rwl, NULL);
    if (pthread_rwlock_init_ret != 0)
    {
        perror("pthread_rwlock_init");
        exit(-1);
    }
    else
    {
        printf("读写锁初始化成功!\n");
    }
    pthread_t pid1, pid2;
    pthread_create(&pid1, NULL, Pthread_Task, (void *)1);
    sleep(1);
    pthread_create(&pid2, NULL, Pthread_Task, (void *)2);
    pause();
}


代码实现效果:

相关文章
|
存储 Linux API
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
在计算机系统的底层架构中,操作系统肩负着资源管理与任务调度的重任。当我们启动各类应用程序时,其背后复杂的运作机制便悄然展开。程序,作为静态的指令集合,如何在系统中实现动态执行?本文带你一探究竟!
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
|
12月前
|
设计模式 消息中间件 安全
【JUC】(3)常见的设计模式概念分析与多把锁使用场景!!理解线程状态转换条件!带你深入JUC!!文章全程笔记干货!!
JUC专栏第三篇,带你继续深入JUC! 本篇文章涵盖内容:保护性暂停、生产者与消费者、Park&unPark、线程转换条件、多把锁情况分析、可重入锁、顺序控制 笔记共享!!文章全程干货!
553 1
|
并行计算 Linux
Linux内核中的线程和进程实现详解
了解进程和线程如何工作,可以帮助我们更好地编写程序,充分利用多核CPU,实现并行计算,提高系统的响应速度和计算效能。记住,适当平衡进程和线程的使用,既要拥有独立空间的'兄弟',也需要在'家庭'中分享和并行的成员。对于这个世界,现在,你应该有一个全新的认识。
542 67
|
并行计算 安全 Java
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
在Python开发中,GIL(全局解释器锁)一直备受关注。本文基于CPython解释器,探讨GIL的技术本质及其对程序性能的影响。GIL确保同一时刻只有一个线程执行代码,以保护内存管理的安全性,但也限制了多线程并行计算的效率。文章分析了GIL的必要性、局限性,并介绍了多进程、异步编程等替代方案。尽管Python 3.13计划移除GIL,但该特性至少要到2028年才会默认禁用,因此理解GIL仍至关重要。
1460 16
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
|
Linux C语言
Linux读写锁源码分析
本文分析了读写锁的实现原理与应用场景,基于glibc 2.17源码。读写锁通过读引用计数、写线程ID、条件变量等实现,支持读优先(默认)和写优先模式。读优先时,写锁可能饥饿;写优先时,读线程需等待写锁释放。详细解析了`pthread_rwlock_t`数据结构及加解锁流程,并通过实验验证:2000个读线程与1个写线程测试下,读优先导致写锁饥饿,写优先则正常抢占锁。
544 19
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
407 26
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
386 17
|
Linux 应用服务中间件 Shell
二、Linux文本处理与文件操作核心命令
熟悉了Linux的基本“行走”后,就该拿起真正的“工具”干活了。用grep这个“放大镜”在文件里搜索内容,用find这个“探测器”在系统中寻找文件,再用tar把东西打包带走。最关键的是要学会使用管道符|,它像一条流水线,能把这些命令串联起来,让简单工具组合出强大的功能,比如 ps -ef | grep 'nginx' 就能快速找出nginx进程。
1127 1
二、Linux文本处理与文件操作核心命令
linux命令—stat
`stat` 是 Linux 系统中用于查看文件或文件系统详细状态信息的命令。相比 `ls -l`,它提供更全面的信息,包括文件大小、权限、所有者、时间戳(最后访问、修改、状态变更时间)、inode 号、设备信息等。其常用选项包括 `-f` 查看文件系统状态、`-t` 以简洁格式输出、`-L` 跟踪符号链接,以及 `-c` 或 `--format` 自定义输出格式。通过这些选项,用户可以灵活获取所需信息,适用于系统调试、权限检查、磁盘管理等场景。
830 137
|
安全 Ubuntu Unix
一、初识 Linux 与基本命令
玩转Linux命令行,就像探索一座新城市。首先要熟悉它的“地图”,也就是/根目录下/etc(放配置)、/home(住家)这些核心区域。然后掌握几个“生存口令”:用ls看周围,cd去别处,mkdir建新房,cp/mv搬东西,再用cat或tail看文件内容。最后,别忘了随时按Tab键,它能帮你自动补全命令和路径,是提高效率的第一神器。
1798 58