关于Qt QReadWriteLock(读写锁) 以及 QSettings 使用的问题

关于Qt QReadWriteLock(读写锁) 使用的问题

经过

我使用这个类实现了一个全局单例对象,用来让程序读取和保存配置文件,但是在软件使用中发生了不明原因的耗时长的问题,经过排查,发现是因为读锁获取时导致的耗时,继而寻找资料结合实际调试经验确认如下问题:

复制代码
当系统进入"写多读少"模式时,QReadWriteLock 的实现通常会优先保障写线程的互斥访问,以避免写饥饿。这导致:
新来的读线程无法获得读锁,即使已有读线程正在运行
写线程持续抢占,形成"写者优先"调度
读线程长时间处于等待队列中,出现"读饥饿"现象
这种机制虽然防止了写操作被无限延迟,但牺牲了读操作的响应性。

引用自QReadLocker在写操作频繁时为何性能下降?

因此读写锁在存在写入操作时,会导致读操作长期处理阻塞转态,且会加剧读队列

QSettings 类

此类是Qt跨平台的配置文件操作类,保证线程及进程安全,并且使用QMap自带数据缓存,理论上直接使用此类是可以满足高速配置文件参数的要求的.

但是经过我的测试,此类在多写的环境中会导致读取性能暴跌,于是翻看源码

查看value 源码

QSettings::value 是调用的QSettingsPrivate::value 函数

其中get函数

复制代码
 const auto locker = qt_scoped_lock(confFile->mutex);

这行代码获取了当前文件对象的排他锁

查看setValue 源码

其中set函数中都是更新的QMap的值

requestUpdate函数,此函数实现了将这个写操作新建成一个事件,并投递到QSettings 实例队列中

然后再查看事件处理函数,里面调用了update函数,update中调用了flush(),flush中调用了sync(),sync中调用了syncConfFile()

syncConfFile函数中实现了将数据写入文件的操作,是个耗时操作具体代码我就不贴了,同志们可以自行查看

sync函数中使用了const auto locker = qt_scoped_lock(confFile->mutex);

即直接把每次的事件都直接使用锁锁住,但是我们的读取操作是需要获取这个锁的

导致的结果就是当写入操作很多的时候,就会导致读取操作阻塞

其实我觉得这个锁操作应该放入syncConfFile函数中,把文件操作那一套操作排除在锁外,就不会有这个问题

完结~

相关推荐
adinnet20268 小时前
企业级 NL2SQL 的重要基础:数据库 Schema 自动理解与元数据管理
数据库
IvorySQL8 小时前
PostgreSQL 日报| OpenCode 遭黑客入侵 API 密钥失窃(10 月 20 日)
数据库·postgresql·区块链
鶴哥只手遮天9 小时前
Spring AI Alibaba 深度技术系列-第 05 章 编译与执行引擎:CompiledGraph、GraphRunner与三段式 Executor
java·人工智能·开源
Elastic 中国社区官方博客9 小时前
控制告警如何触发、恢复和发送通知:Elastic 可观测性中的 Kibana 通用告警
大数据·数据库·安全·elasticsearch·搜索引擎·全文检索·es
GlobalInfo9 小时前
全球人工智能数据中心保险市场动态、发展趋势及项目可行性研究报告2026-2032
数据库·人工智能·ai·数据中心
星马梦缘9 小时前
关于人工智能学院游戏设计大赛决赛的内部分工通知
数据库·人工智能·游戏
开开心心_Every9 小时前
免费压缩软件WinRAR无弹窗、广告干扰
java·开发语言·前端·spring·智能手机·word·winrar
Databend9 小时前
以云原生湖仓支撑 AI 应用落地丨Databend 亮相 2026 人工智能开放计算大会
大数据·数据库·数据分析
计算机毕设定制辅导-无忧学长9 小时前
《基于微信小程序的个人智能刷题助手的设计与实现》
java·spring boot·mysql·微信小程序·uniapp·个人智能刷题助手系统
geovindu9 小时前
sql:Managing Complex Joins and Subqueries in SQL using mysql 9.0
大数据·数据库·数据仓库·sql·mysql·数据库开发·数据库架构