首页 > 系统相关 >Linux线程之读写锁小结

Linux线程之读写锁小结

时间:2024-06-01 20:46:09浏览次数:31  
标签:rwlock thread Linux am tm 线程 time pthread 小结

读写锁(rwlock)与互斥锁(Mutex Lock)相比,有如下特点:

  • 更加细致的区分了读和写,给共享资源分别上了“读”锁和“写”锁。
  • “写”独占,“读”共享,“写”锁优先级更高
  • 如果共享资源在绝大多数情况下是“读”操作,可以提高程序的并发性能。

常用的函数原型总结如下:

pthread_rwlock_t rwlock (= PTHREAD_RWLOCK_INITIALIZER); // 定义读写锁的变量并初始化,一定要全局变量,如果使用了下述初始化函数,括号内静态初始化就可以取消
pthread_rwlock_init(&rwlock, NULL);                       // const pthread_rwlockattr_t *restrict attr,第二个参数默认为NULL
pthread_rwlock_rdlock(&rwlock);                           // 上读锁,并进行读操作
pthread_rwlock_wrlock(&rwlock);                           // 上写锁,并进行写操作,同一时间只有一把写锁,并与其他锁互斥
pthread_rwlock_unlock(&rwlock);                           // 解锁,读和写的解锁函数都相同
pthread_rwlock_destroy(&rwlock);                          // 不用了就销毁读写锁

设计一个程序,程序中有3个线程,主线程A创建一个文本,每隔5s获取一次系统时间并写入到该文本中,另外两个线程B和C分别从文本中读取当前的时间和日期,子线程B输出系统时间"hh:mm:ss",子线程c输出系统日期"2024年05月31日”,要求使用读写锁实现互斥。 提示:主线程A获取写操作的锁,另外的线程分别获取读操作的锁,程序如下:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>

FILE *timefp;            // 以文件句柄为共享区
pthread_rwlock_t rwlock; // 定义读写锁的变量,一定要全局变量

// 需要用到的时间结构体,提前列出
//  struct tm {
//                 int tm_sec;    /* Seconds (0-60) */
//  int tm_min;   /* Minutes (0-59) */
//  int tm_hour;  /* Hours (0-23) */
//  int tm_mday;  /* Day of the month (1-31) */
//  int tm_mon;   /* Month (0-11) */
//  int tm_year;  /* Year - 1900 */
//  int tm_wday;  /* Day of the week (0-6, Sunday = 0) */
//  int tm_yday;  /* Day in the year (0-365, 1 Jan = 0) */
//  int tm_isdst; /* Daylight saving time */
//  }

void *funcB(void *arg) // B线程
{

    time_t tlocB = 0;
    while (1)
    {
        pthread_rwlock_rdlock(&rwlock); // 上锁,进行读操作
        timefp = fopen("/home/rice/0531/time.txt", "r+");
        fread(&tlocB, sizeof(time_t), 1, timefp);
        struct tm *tt = localtime(&tlocB);
        printf("I am thread B,the time is ===== %02d:%02d:%02d\n", tt->tm_hour, tt->tm_min, tt->tm_sec);
        pthread_rwlock_unlock(&rwlock); // 解锁,释放权限
        fclose(timefp);
        sleep(2); // 每隔两秒进行一次输出
    }
}
void *funcC(void *arg)
{
    time_t tlocC = 0;
    while (1)
    {
        pthread_rwlock_rdlock(&rwlock); // 上锁,进行读操作
        timefp = fopen("/home/rice/0531/time.txt", "rb+");
        fread(&tlocC, sizeof(time_t), 1, timefp);
        struct tm *tt = localtime(&tlocC);
        printf("I am thread C,the date is ===== %d年:%02d月:%02d日\n", tt->tm_year + 1900, tt->tm_mon + 1, tt->tm_mday);
        pthread_rwlock_unlock(&rwlock); // 解锁,释放权限
        fclose(timefp);
        sleep(2); // 每隔两秒进行一次输出
    }
}

int main()
{
    pthread_rwlock_init(&rwlock, NULL); // 初始化读写锁

    pthread_t tidB, tidC;
    pthread_create(&tidB, NULL, funcB, NULL); // 创建线程
    pthread_create(&tidC, NULL, funcC, NULL);

    while (1) // 主线程每隔5秒获取一次系统时间
    {
        pthread_rwlock_wrlock(&rwlock); // 上锁,进行写操作

        timefp = fopen("/home/rice/0531/time.txt", "wb+"); // 打开文件,不存在就创建
        time_t tloc = time(NULL);
        fwrite(&tloc, sizeof(time_t), 1, timefp); // 将time原始数据存入文件
        fclose(timefp);
        pthread_rwlock_unlock(&rwlock); // 解锁,释放文件权限
        sleep(5);                       // 每隔5秒进行一次写入操作
    }

    // 等待B和C线程结束
    pthread_join(tidB, NULL);
    pthread_join(tidC, NULL);
    // 销毁读写锁
    pthread_rwlock_destroy(&rwlock);

    return 0;
}

输出结果如下:

I am thread B,the time is ===== 20:10:57
I am thread C,the date is ===== 2024年:06月:01日
I am thread B,the time is ===== 20:10:57
I am thread C,the date is ===== 2024年:06月:01日
I am thread C,the date is ===== 2024年:06月:01日
I am thread B,the time is ===== 20:10:57
I am thread B,the time is ===== 20:11:02
I am thread C,the date is ===== 2024年:06月:01日
I am thread B,the time is ===== 20:11:02
I am thread C,the date is ===== 2024年:06月:01日
...

标签:rwlock,thread,Linux,am,tm,线程,time,pthread,小结
From: https://www.cnblogs.com/cino/p/18226365

相关文章

  • Linux上安装jdk
    1).上传安装包使用FinalShell自带的上传工具将jdk的二进制发布包上传到Linux上传完毕后,我们执行指令cd/切换到上传目录下,查看上传的安装包。2).解压安装包执行如下指令,将上传上来的压缩包进行解压,并通过-C参数指定解压文件存放目录为/usr/local。(注意版本和压缩包后缀)......
  • 【Linux】 深入讲解自动化构建工具
    各位大佬好,这里是阿川的博客,祝您变得更强个人主页:在线OJ的阿川大佬的支持和鼓励,将是我成长路上最大的动力阿川水平有限,如有错误,欢迎大佬指正Linux一系列的文章(质量分均在93分以上)Linux–发展、环境、指令上半场Linux–指令下半场Linux–权限Linux–生态与......
  • 单例模式线程安全reorder问题
    单例模式是一种常用的软件设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。下面是一个使用C++实现的线程安全的单例模式的例子:classSingleton{private:staticstd::atomic<Singleton*>instance;//静态私有实例指针使用原子操作类atomic线程安全sta......
  • 【Linux基础】tomcat安装
    【Linux基础】tomcat安装文章目录【Linux基础】tomcat安装1、Linux安装软件方式2、安装jdk3、安装tomcat4、防火墙操作5、tomcat停止1、Linux安装软件方式在Linux系统中,安装软件的方式主要有四种,这四种安装方式的特点如下:安装方式特点二进制发布包安装软件已经......
  • 【LInux内核中IO多路复用 背景+原理+直白总结+优缺点】EPoll篇 及大总结
    Linux内核中的epoll多路复用原理是基于事件驱动的一种高效I/O处理机制,它主要用于监视多个文件描述符(filedescriptors,简称fd)的状态并进行事件驱动的I/O操作。epoll相比传统的select和poll机制,在处理大量并发连接时具有更高的效率和更低的资源消耗。以下是epoll多路复用原理......
  • [转帖]在Linux上查看活跃线程数与连接数
     https://www.cnblogs.com/xibuhaohao/p/11413669.html 原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,非公众号转载保留此声明。简介现如今,有两种常见的软件资源几乎成了Java后端程序的标配,即线程池与连接池,但这些池化资源非常的重要,一旦不够用了,就会导致程序阻塞、性能......
  • CentOS Linux 8x 错误:为仓库 ‘appstream‘ 下载元数据失败 : Cannot prepare interna
    问题描述今天安装CentOS8.5安装完之后,准备更新源仓库环境的时候突然出现错误:为仓库'appstream'下载元数据失败:Cannotprepareinternalmirrorlist:NoURLsinmirrorlist,后面我找了好久没发现有解决这个问题的方法,后面无意看到了https://www.cnblogs.com/cainiaoaixuexi......
  • Linux 常用命令宝典(超详细) (下)
    书接上回14、管道符“|”cattest.txt|grep'world' #把前边的查询结果,当做后边的数据源来处理.#查询test文档中所有存在'world'的行.15、tail命令#格式:tail[-num-f]要查看的文件 -num:看(末尾)几行-f:持续追踪tailte......
  • Linux 常用命令宝典(超详细) (上)
            在职场中,有很多运维或者开发工作都需要通过命令来完成,很少有用到图形界面。作为一名后端程序员我们必须掌握一些Linux常用的终端命令。Linux发行版的命令大概有200多个,常用的命令有二十余个,本文将详细介绍这些命令。Linux命令格式:#Linux命令格式,如下的......
  • 从网络启动Linux
    目录从网络启动Linux1、提供所需文件2、U-Boot的烧录3、网络配置4、放置内核、设备树文件、根文件系统5、启动Linux从网络启动Linux1、提供所需文件启动需要的mfgtool、linux内核镜像文件zImage、设备树文件.dtb、根文件系统。这些所需资源我都整理和调试后放在云......