freeswitch APR库线程读写锁

概述
freeswitch的核心源代码是基于apr库开发的,在不同的系统上有很好的移植性。
线程读写锁在多线程服务中有重要的作用。对于读数据比写数据频繁的服务,用读写锁代替互斥锁可以提高效率。
由于APR库是跨平台的,而不同平台上的系统接口有区别,所以在APR库中就有一个适配层目录libs\apr\include\arch\,该目录下有不同系统的头文件定义,包括aix、beos、netware、os2、os390、unix、win32。
在编译源代码文件的过程中,根据当前系统自动选择不同的文件目录来适配。
下面我们对apr库的线程读写锁实现做一个介绍。
环境
centos:CentOS release 7.0 (Final)或以上版本
freeswitch:v1.8.7
GCC:4.8.5
读写锁数据结构
apr库的线程读写锁源代码文件在libs/apr目录下,这里只列出了unix和win32的版本。
libs\apr\include\apr_thread_rwlock.h
libs\apr\include\arch\unix\apr_arch_thread_rwlock.h
libs\apr\locks\unix\thread_rwlock.c
libs\apr\include\arch\win32\apr_arch_thread_rwlock.h
libs\apr\locks\win32\thread_rwlock.c
读写锁结构体定义。
我们可以看出,在unix系统下直接使用了pthread线程库的读写锁实现。
libs\apr\include\arch\unix\apr_arch_thread_rwlock.h
struct apr_thread_rwlock_t {
apr_pool_t *pool;
pthread_rwlock_t rwlock;
};
在win32系统则是使用了临界区CRITICAL_SECTION、mutex和event协同实现。
libs\apr\include\arch\win32\apr_arch_thread_rwlock.h
struct apr_thread_rwlock_t {
apr_pool_t *pool;
HANDLE write_mutex;
HANDLE read_event;
LONG readers;
CRITICAL_SECTION read_section;
};
常用函数
查看源代码头文件libs\apr\include\apr_thread_rwlock.h。
apr_thread_rwlock_create //创建并初始化1个线程读写锁
apr_thread_rwlock_rdlock //获取1个共享读锁
apr_thread_rwlock_tryrdlock //非阻塞获取1个共享读锁
apr_thread_rwlock_wrlock //获取1个独占写锁
apr_thread_rwlock_trywrlock //非阻塞获取1个独占写锁
apr_thread_rwlock_unlock //解锁1个读写锁
apr_thread_rwlock_destroy //销毁读写锁
从接口定义我们可以看出,加读锁和加写锁是分开的接口,而解锁是同一个接口。
接口的实现我们简单介绍一下。
在unix系统下,读写锁的接口中直接调用了pthread库中对应的读写锁接口。
比如apr_thread_rwlock_create中调用了pthread_rwlock_init,apr_thread_rwlock_rdlock中调用了pthread_rwlock_rdlock等等,这里就不再详细展开了,有兴趣的可以自己查看一下pthread_rwlock_t读写锁的定义和实现。
在win32系统下,读写锁的接口中使用了readers、read_event、write_mutex和read_section几个变量共同实现了读写锁的功能。
伪代码-读锁(读写锁, 超时时间)
进入临界区read_section
等待信号write_mutex,失败或超时则返回错误
计数器readers+1
重置事件read_event,失败则返回错误
释放write_mutex,失败则返回错误
离开临界区read_section
返回成功
伪代码-写锁(读写锁, 超时时间)
等待信号write_mutex,失败或超时则返回错误
等待信号read_event,失败或超时则释放write_mutex,并返回错误
返回成功
伪代码-解锁(读写锁)
释放write_mutex
计数器readers-1
设置事件read_event
返回
说实话。。。win32的代码我没看懂,有没有win开发的高手给讲解一下。
比如,为什么只有读锁中有临界区read_section的操作,为什么write_mutex只有释放操作,为什么写锁中没有等待readers为0。。。
总结
apr库的线程读写锁的实现介绍完了。
读写锁的适用场景是多线程下读多写少的业务流程,以实现独占写和共享读的逻辑。
在合适的场景中,读写锁比互斥锁有更高的并发能力和效率。
另外,还有强读者和强写者俩种不同的形式,读者可以自己深入研究一下。
空空如常
求真得真
freeswitch APR库线程读写锁的更多相关文章
- freeswitch APR库
概述 freeswitch依赖库源代码基本都可以在libs目录下找到. 在freeswitch的官方手册中,可以找到freeswitch的依赖库表格,其中freeswitch的core核心代码依赖库主 ...
- freeswitch APR库哈希表
概述 freeswitch的核心源代码是基于apr库开发的,在不同的系统上有很好的移植性. 哈希表在开发中应用的非常广泛,主要场景是对查询效率要求较高的逻辑,是典型的空间换时间的数据结构实现. 大多数 ...
- freeswitch APR-UTIL库线程池实现分析
概述 freeswitch的核心源代码是基于apr库开发的,在不同的系统上有很好的移植性. APR库在之前的文章中已经介绍过了,APR-UTIL库是和APR并列的工具库,它们都是由APACHE开源出来 ...
- Java线程读写锁
排他锁和共享锁: 读写锁:既是排他锁,又是共享锁.读锁,共享锁,写锁:排他锁 读和读是不互斥的 import java.util.HashMap; import java.util.Map; impo ...
- Java 线程锁机制 -Synchronized Lock 互斥锁 读写锁
(1)synchronized 是互斥锁: (2)ReentrantLock 顾名思义 :可重入锁 (3)ReadWriteLock :读写锁 读写锁特点: a)多个读者可以同时进行读b)写者必须互斥 ...
- Java基础-Java中的并法库之重入读写锁(ReentrantReadWriteLock)
Java基础-Java中的并法库之重入读写锁(ReentrantReadWriteLock) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在学习Java的之前,你可能已经听说过读 ...
- C#使用读写锁三行代码简单解决多线程并发写入文件时线程同步的问题
(补充:初始化FileStream时使用包含文件共享属性(System.IO.FileShare)的构造函数比使用自定义线程锁更为安全和高效,更多内容可点击参阅) 在开发程序的过程中,难免少不了写入错 ...
- linux线程同步(3)-读写锁
一.概述 读写锁与互斥量的功能类似,对临界区的共享资源进行保护!互斥量一次只让一个线程进入临界区, ...
- 第8章 用户模式下的线程同步(3)_Slim读写锁(SRWLock)
8.5 Slim读/写锁(SRWLock)——轻量级的读写锁 (1)SRWLock锁的目的 ①允许读者线程同一时刻访问共享资源(因为不存在破坏数据的风险) ②写者线程应独占资源的访问权,任何其他线程( ...
随机推荐
- 大爽Python入门教程 0-1 安装python
大爽Python入门公开课教案 点击查看教程总目录 一 如何找到下载地址并下载 下面展示找到下载地址的方法步骤 嫌步骤太慢可直接跳到第4步, 查看详细下载地址 使用搜索引擎搜索python 打开搜索结 ...
- ESP32-S3 搭建 micropython 开发环境,固件编译,烧录
简述 上手了一块乐鑫科技官方推出的ESP32-S3-DevKitC-1开发板,发现 ESP32-S3 的综合性能较比前两代有着非常明显的提升,wifi与蓝牙功能,更充足的外设扩展能力,可以看出其在未来 ...
- 麒麟Linux上编译subversion
麒麟Linux上编译subversion svn-1.7不支持svn info --show-item=revision[1]获取revision. svn-1.12开始不能保存密码stackover ...
- [cf1515I]Phoenix and Diamonds
将$n$类物品按照价值为第一关键字(从大到小).质量为第二关键字(从小到大)排序,此时贪心策略即依次贪心选(排序后)第$i$类的物品(其中$i$从1到$n$) 为了方便,排序后第$i$类物品质量.价值 ...
- App 端自动化的最佳方案,完全解放双手!
1. 前言 大家好,我是安果! 之前写过一篇文章,文中提出了一种方案,可以实现每天自动给微信群群发新闻早报 如何利用 Python 爬虫实现给微信群发新闻早报?(详细) 但是对于很多人来说,首先编写一 ...
- Python的数据解析
- Swift-技巧(九)CGImage To CVPixelBuffer
摘要 iOS 中图像的表现形式不只是 Image,还有更加底层的方式,比如 CVPixelBuffer 像素缓存形式,那么 CGImage 就可以转换为像素缓存的方式也是需要了解的. CGImage ...
- C/C++ Qt TableDelegate 自定义代理组件
TableDelegate 自定义代理组件的主要作用是对原有表格进行调整,例如默认情况下Table中的缺省代理就是一个编辑框,我们只能够在编辑框内输入数据,而有时我们想选择数据而不是输入,此时就需要重 ...
- [JSC2021 A~D + F]
半小时打完了\(A~D\),想要一发\(F\)冲进前\(100\),结果平衡树常数大\(T\)了.据说\(G\)是矩阵树定. \(A\) 放代码吧. A // code by Dix_ #includ ...
- 模版 动态 dp
模版 动态 dp 终于来写这个东西了.. LG 模版:给定 n 个点的数,点有点权, $ m $ 次修改点权,求修改完后这个树的最大独立集大小. 我们先来考虑朴素的最大独立集的 dp \[dp[u][ ...