Linux之线程-读写锁pthread_rwlock_t

**主要内容:
(1)互斥量及如何使用
(2)什么是死锁,如何解决
(3)什么是读写锁,如何使用**
(4)条件变量实现的生产消费者模型
(5)信号量实现的生产消费者模型

3.读写锁

特点:读共享,写独占,写优先级高。读写锁仍然是一把锁,有不同的状态:未加锁、读锁和写锁。

场景:适合读的线程较多的情况

  1. 线程A加写锁成功,线程B请求读锁。--线程B阻塞
  2. 线程A持有读锁,线程B请求写锁。--线程B阻塞
  3. 线程A持有读锁,线程B请求读锁。--B加锁成功
  4. 线程A持有读锁,然后线程B请求读锁,然后线程C请求写锁。--BC阻塞--A释放,C加锁--C释放B加锁
  5. 线程A持有写锁,然后线程B请求读锁,然后线程C请求写锁。--BC阻塞--A释放,C加锁--C释放B加锁

函数原型:#include <pthread.h>

(1)读写锁初始化

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

(2)摧毁读写锁

  • int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

(3)加读锁

  • int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);  //成功返回0,错误返回an error number shall be returned to indicate the error.

  •  int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);  //同上

(4)加写锁

  • int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

(5)释放锁

  • int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

示例:

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

pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;  //读写锁初始化
int beginnum = 1000;

void *thr_write(void *arg)
{
    while (1)
    {
        pthread_rwlock_wrlock(&rwlock);
        printf("------%s-----self----%lu---beginnum----%d\n",__FUNCTION__,pthread_self(),++beginnum);
        usleep(2000); //模拟占用时间
        pthread_rwlock_unlock(&rwlock);
        usleep(4000);
    }
    
    return NULL;
}

void *thr_read(void *arg)
{
    while (1)
    {
        pthread_rwlock_rdlock(&rwlock);
        printf("------%s-----self----%lu---beginnum----%d\n",__FUNCTION__,pthread_self(),beginnum);
        usleep(2000); //模拟占用时间
        pthread_rwlock_unlock(&rwlock);
        usleep(2000);
    }

    return NULL;

}

int main()
{
    int n =8, i = 0;
    pthread_t tid[8];  //5-read, 3-write
    for(i = 0; i < 5; i++)
    {
        pthread_create(&tid[i],NULL,thr_read,NULL);
    }

    for(i = 0; i < 3; i++)
    {
        pthread_create(&tid[i],NULL,thr_write,NULL);
    }

    for(i=0; i < 8; i++)
    {
        pthread_join(tid[i],NULL);
    }
    return 0;
}

输出:

~$ gcc rwlock.c -lpthread
~$ ./a.out
------thr_read-----self----140403159697152---beginnum----1000
------thr_read-----self----140403151304448---beginnum----1000
------thr_read-----self----140403126126336---beginnum----1000
------thr_read-----self----140403134519040---beginnum----1000
------thr_read-----self----140403142911744---beginnum----1000
------thr_write-----self----140403117733632---beginnum----1001
------thr_write-----self----140403109340928---beginnum----1002
------thr_write-----self----140403100948224---beginnum----1003
------thr_write-----self----140403117733632---beginnum----1004
------thr_write-----self----140403109340928---beginnum----1005
------thr_write-----self----140403100948224---beginnum----1006
------thr_write-----self----140403117733632---beginnum----1007
------thr_write-----self----140403109340928---beginnum----1008
------thr_write-----self----140403100948224---beginnum----1009
------thr_write-----self----140403117733632---beginnum----1010
------thr_write-----self----140403109340928---beginnum----1011
------thr_write-----self----140403100948224---beginnum----1012
------thr_write-----self----140403117733632---beginnum----1013

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
在基于 rt-thread 的系统中,可以使用 `struct rt_semaphore` 结构体来实现的控制。具体实现可以参考以下代码: ``` struct rt_semaphore rw_sem; int read_count; /* 初始化 */ int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) { /* 初始化信号量,初始值为 1 */ rt_sem_init(&rw_sem, "rw_sem", 1, RT_IPC_FLAG_FIFO); read_count = 0; return 0; } /* 销毁 */ int pthread_rwlock_destroy(pthread_rwlock_t *rwlock) { /* 删除信号量 */ rt_sem_delete(&rw_sem); return 0; } /* 对进行定 */ int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) { /* 获取信号量,如果信号量值为 0,则线程阻塞 */ rt_sem_take(&rw_sem, RT_WAITING_FOREVER); read_count++; return 0; } /* 对进行定 */ int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) { /* 获取信号量,如果信号量值为 0,则线程阻塞 */ rt_sem_take(&rw_sem, RT_WAITING_FOREVER); while (read_count > 0) { /* 如果有线程在使用,则等待线程全部释放 */ rt_sem_release(&rw_sem); rt_sem_take(&rw_sem, RT_WAITING_FOREVER); } return 0; } /* 对进行解 */ int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) { /* 释放信号量 */ rt_sem_release(&rw_sem); read_count--; return 0; } ``` 在上述代码中,我们使用了一个信号量来实现的控制。信号量的初始值为 1,表示是未定状态。当线程需要对进行定时,首先需要获取信号量,如果信号量的值为 0,则线程阻塞等待。对于,只需要将计数器 `read_count` 加 1 即可;对于,则需要判断是否有线程在使用,如果有,则等待线程全部释放后再获取。对于解操作,只需要释放信号量并将计数器减 1 即可。 上述代码中的函数名和参数与 POSIX 标准中定义的函数名和参数保持一致,因此可以直接调用这些函数来实现的控制。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值