QT的互斥量和信号量

文章目录

  • 一、mutex互斥量
    • 1、mutex
    • 2、相关成员函数
  • 二、semaphore信号量
    • 1、信号量
    • 2、成员函数
  • 三、Linux内核中的互斥锁、读写锁、自旋锁、信号量
  • 四、QT简单日志类代码

一、mutex互斥量

1、mutex

目的是保护对象、数据结构或代码段,以便一次只有一个线程可以访问它。

QMutex mutex;
int number = 6;void method1()
{mutex.lock();number *= 5;number /= 4;mutex.unlock();
}void method2()
{mutex.lock();number *= 3;number /= 2;mutex.unlock();
}

2、相关成员函数

QMutex::QMutex(QMutex::RecursionMode mode)
//构造一个新的互斥对象。互斥锁是在未锁定状态下创建的。
//如果模式是QMutex::Recursive,则线程可以多次锁定同一个互斥对象,
//并且在进行相应数量的unlock()调用之前,该互斥对象不会被解锁。
//否则,线程可能只锁定一次互斥对象。默认值为QMutex::NonRecursive。
//递归互斥量比非递归互斥量慢,占用的内存也更多。
bool QMutex::isRecursive() const
//如果这个互斥量为递归返回true.
void QMutex::lock()
//锁定互斥对象。如果另一个线程锁定了互斥锁,那么这个调用将被阻塞,直到该线程将其解锁。
//如果该互斥对象是递归互斥对象,则允许在同一线程的同一互斥对象上多次调用该函数。
//如果这个互斥对象是非递归互斥对象,那么当互斥对象被递归锁定时,这个函数将死锁定。
bool QMutex::try_lock()
//尝试锁定互斥对象。如果已获得锁,此函数将返回true;否则返回false。
//提供此功能是为了与标准库概念Lockable兼容。它相当于tryLock()。bool QMutex::tryLock(int timeout = 0)
//尝试锁定互斥对象。如果已获得锁,此函数将返回true;否则返回false。
//如果另一个线程锁定了互斥锁,则此函数最多会等待超时毫秒,以便互斥锁可用。
template <typename Rep, typename Period> bool QMutex::try_lock_for(std::chrono::duration<Rep, Period> duration)
//尝试锁定互斥对象。如果已获得锁,此函数将返回true;否则返回false。
//如果另一个线程锁定了互斥锁,此函数将等待duration时间,以使互斥锁可用。
//注意:传递一个负的持续时间作为持续时间相当于调用try_lock()。此行为与tryLock()不同。
template <typename Clock, typename Duration> bool QMutex::try_lock_until(std::chrono::time_point<Clock, Duration> timePoint)
//尝试锁定互斥对象。如果已获得锁,此函数将返回true;否则返回false。
//如果另一个线程锁定了互斥锁,此函数将等待timepoint时间,以使互斥锁可用。
//注意:传递一个timepoint作为持续时间相当于调用try_lock()。此行为与tryLock()不同。
以上三个方法
//如果获得了锁,则必须使用unlock()解锁互斥锁,然后另一个线程才能成功锁定它。
//如果该互斥对象是递归互斥对象,则允许在同一线程的同一互斥对象上多次调用该函数。
//如果这个互斥锁是非递归互斥锁,那么当试图递归锁定互斥锁时,这个函数总是返回false。
void QMutex::unlock()
//解锁互斥锁。试图解锁与锁定互斥锁的线程不同的线程中的互斥锁会导致错误。
//解锁未锁定的互斥对象会导致未定义的行为。

二、semaphore信号量

1、信号量

信号量是互斥锁的一种推广。信号量通常用于保护一定数量的相同资源。信号量支持两种基本的操作,acquire()release()。**acquire(n)**尝试获取n个资源,如果没有那么多可用资源,那么调用将被阻止,直到可以获取到n个资源;release(n) 释放n个资源。

QSemaphore sem(5);      // sem.available() == 5sem.acquire(3);         // sem.available() == 2
sem.acquire(2);         // sem.available() == 0
sem.release(5);         // sem.available() == 5
sem.release(5);         // sem.available() == 10,此时资源数超过初始值sem.tryAcquire(1);      // sem.available() == 9, returns true
sem.tryAcquire(250);    // sem.available() == 9, returns false

2、成员函数

QSemaphore::QSemaphore(int n = 0)
//创建新的信号量并且初始化资源的数量,资源视为n,默认为0;
void QSemaphore::acquire(int n = 1)
//尝试获取信号量保护的n个资源。如果n>available(),则此调用将阻塞,直到有足够的资源可用为止。
int QSemaphore::available() const
//返回信号量当前可用的资源数。这个数字永远不能是负数。
void QSemaphore::release(int n = 1)
//释放n个信号量保护的资源
bool QSemaphore::tryAcquire(int n = 1)
//尝试获取n个信号量保护的资源,如果获取到返回为true,
//如果 available() < n,则立即返回false,不会调用任何资源
bool QSemaphore::tryAcquire(int n, int timeout)
//尝试获取n个信号量保护的资源,如果获取到返回为true,
//如果available()<n,则此调用最多将等待超时毫秒,以便资源变为可用。
//注意:传递一个负数作为超时相当于调用acquire(),即如果超时为负数,此函数将永远等待资源可用。

三、Linux内核中的互斥锁、读写锁、自旋锁、信号量

1、互斥锁(mutex) 是最常用的锁,它可以保护共享资源,使得在某个时刻只有一个线程或进程可以访问它。读写锁(rwlock)则可以同时允许多个线程或进程读取共享资源,但只允许一个线程或进程写入它。自旋锁(spinlock)可以用来保护共享资源,使得在某个时刻只有一个线程或进程可以访问它,但它会使线程或进程“自旋”,直到获得锁为止。最后,信号量(semaphore)可以用来控制对共享资源的访问,以保证其他线程或进程可以安全地访问它们。

2、读写锁(rwlock) 是一种用于控制多线程访问共享资源的同步机制。当一个线程需要读取共享资源时,可以获取读取锁,这样其他线程就可以同时读取该资源,而不会引发冲突。当一个线程需要写入共享资源时,可以获取写入锁,这样其他线程就不能访问该资源,从而保证数据的完整性和一致性。

3、自旋锁(spinlock) 是一种简单而有效的用于解决多线程同步问题的锁。它是一种排他锁,可以在多线程环境下保护共享资源,以防止多个线程同时对该资源进行访问。自旋锁的基本原理是,当一个线程试图获取锁时,它会不断尝试获取锁,直到成功为止。在这期间,线程不会进入休眠状态,而是一直处于忙等待(busy-waiting)状态,这也就是自旋锁的由来。

4、信号量(semaphore) 是一种常用的同步机制,它可以用来控制多个线程对共享资源的访问。它有助于确保同一时间只有一个线程能够访问共享资源,从而避免资源冲突和竞争。信号量是一种整数计数器,用于跟踪可用资源的数量。当一个线程需要访问共享资源时,它首先必须获取信号量,这会将信号量的计数器减少1,而当它完成访问共享资源后,它必须释放信号量,以便其他线程也可以访问共享资源。
更多详细介绍

四、QT简单日志类代码

1、头文件

#ifndef LOG_H
#define LOG_H
#include <QDebug>
#include <QDate>
#include <QFile>
#include <QThread>
#include <QList>
#include <QSemaphore>
#include <QMutex>
/***************************************
* 说明:日志功能的单线程实现
* 作者:caokexiang
* 时间:20240522
******************************************/
class QSimpleLog : public QThread
{Q_OBJECT
public:QSimpleLog(QString const& fileName);
public:
/***************************************
* 说明: 将记录写入日志文件(写入中文需要提前使用QString::fromLocal8Bit转变字符格式)
* 参数: msg:待写入的信息
* 作者:caokexiang
* 时间:20240522
******************************************/void write(const QString& msg);virtual void run();
private:QString const fileName; // 文件名QList<QString> m_msg;   //写入线程的消息队列QMutex m_mutex;         //对m_msg进行线程安全保护的互斥信号量QSemaphore m_synSem;    //同步信号量,当消息队列未进入时,线程处于阻塞状态,可以避免while一直死循环
};
#endif

2、源文件

#include "QSimpleLog.h"QSimpleLog::QSimpleLog(QString const &fileName) : m_synSem(0), fileName(fileName){//初始化信号量,初始资源为0
} void QSimpleLog::write(const QString& msg)
{m_mutex.lock();QString currentDateTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");QString message = QString("[%1]: %2").arg(currentDateTime).arg(msg);m_msg.push_back(message);m_mutex.unlock();m_synSem.release(); //资源数增加1
}void QSimpleLog::run()
{while (true){m_synSem.acquire();m_mutex.lock();if (m_msg.isEmpty()){continue;}QString message = m_msg.front();m_msg.pop_front();QFile file(fileName);file.open(QIODevice::WriteOnly | QIODevice::Append);QTextStream text_stream(&file);text_stream << message << "\r\n";file.flush();file.close();m_mutex.unlock();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/18023.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云易办springboot+vue后端

springbootvue云易办后端项目完成 一.创建项目 创建父项目&#xff1a;yeb&#xff0c; 使用spring Initializr&#xff0c;完成创建之后删除无用文件夹&#xff0c;作为父项目 添加packaging <packaging>pom</packaging>二.创建子模块&#xff1a;yeb-server …

Day 56 647. 回文子串 516.最长回文子序列

回文子串 给定一个字符串&#xff0c;你的任务是计算这个字符串中有多少个回文子串。 具有不同开始位置或结束位置的子串&#xff0c;即使是由相同的字符组成&#xff0c;也会被视作不同的子串。 示例 1&#xff1a; 输入&#xff1a;“abc”输出&#xff1a;3解释&#xf…

蓝桥杯—SysTick中断精准定时实现闪烁灯

在嵌入式系统中&#xff0c;SysTick_Handler 是一个中断服务例程&#xff08;Interrupt Service Routine, ISR&#xff09;&#xff0c;用于处理 SysTick 定时器的中断。SysTick 定时器通常用于提供一个周期性的定时中断&#xff0c;可以用来实现延时或者周期性任务。 SysTick…

SQL 语言:数据控制

文章目录 概述授权&#xff08;GRANT)销权&#xff08;REVOKE&#xff09;总结 概述 SQL语言中的数据控制权限分配是数据库管理的重要组成部分&#xff0c;它涉及到如何合理地为用户分配对数据库资源的访问和使用权限。 权限类型&#xff1a;在SQL中&#xff0c;权限主要分为…

【Python-OS】os.path.splitext()

作用&#xff1a;将文件路径分割成文件名和扩展名两部分。 slide_id, _ os.path.splitext(slide) print("slide:") print(slide) print("slide_id:") print(slide_id)注&#xff1a; slide是文件名&#xff0c;可以自行赋值

妙解设计模式之单例模式

目录 单例模式的概念生活中的例子编程中的例子 软件工程中的实际应用配置管理日志管理数据库连接池缓存管理线程池管理 单例模式的概念 单例模式&#xff08;Singleton Pattern&#xff09;是一种设计模式&#xff0c;用于确保一个类在整个程序运行过程中只有一个实例&#xf…

TD3的定义 离线强化学习在医疗领域的应用

1.TD3是什么&#xff1f; TD3全称为Twin Delayed Deep Deterministic policy gradient algorithm&#xff0c;中文名称为孪生延迟深度确定性策略梯度&#xff0c;从英文名称可以看出&#xff0c;TD3是基于DDPG的一个改进算法。直接来说&#xff0c;TD3针对DDPG做出了三个方面的…

【IT小知识】堡垒机支持哪些私有云平台?

随着企业对网络安全的重视&#xff0c;以及等保政策的要求&#xff0c;越来越多的企业打算采购堡垒机。但不少企业对于堡垒机了解不多&#xff0c;一些小伙伴在问&#xff0c;堡垒机支持哪些私有云平台&#xff1f; 堡垒机支持哪些私有云平台&#xff1f; 【回答】&#xff1a…

数据分析必备:一步步教你如何用Pandas做数据分析(10)

1、Pandas 文本处理 Pandas 文本处理操作实例 在本章中&#xff0c;我们将使用基本的Series / Index讨论字符串操作。在随后的章节中&#xff0c;我们将学习如何在DataFrame上应用这些字符串函数。 Pandas提供了一组字符串函数&#xff0c;可以轻松地对字符串数据进行操作。最…

Talken - 语音命令系统

Talken - 语音命令系统 通过集成最先进的语音命令系统 Talken,释放游戏的全部潜力。 借助 Talken,您可以让玩家通过语音命令控制动作,从而重新定义游戏体验。 观看角色移动并对语音指令做出实时反应,模糊游戏与现实之间的界限。 主要特征: 🗣️ 语音驱动的游戏玩法:…

openssh生成ed25519的密钥对并实现服务器间免密钥登录

本文讲解如何用openssh生成ed25519的密钥对并实现服务器间免密钥登录。 注意&#xff1a;所有操作均在客户机侧 一、生成 ED25519 密钥 用需要免密登录的用户&#xff08;本例为username&#xff09; 运行“ssh-keygen -t ed25519 -b 256” [usernamelocalhost ~]$ ssh-keyge…

几个原则

&#xff08;1&#xff09; 成功是成功之母&#xff0c;失败不是成功之母。100分的试卷一模一样&#xff0c;不及格的试卷千奇百怪。向成功者学习。 不要研究失败&#xff0c;因为研究了一万个失败的原因&#xff0c;也不能找到一把成功的钥匙。 &#xff08;2&#xff09; 要定…

自由应用大本营?开源免费的Android应用商店:F-Droid Client

F-Droid Client&#xff1a;拥抱开源&#xff0c;守护隐私&#xff0c;让自由软件成为您生活的一部分- 精选真开源&#xff0c;释放新价值。 概览 F-Droid Client是一个开源的Android应用商店&#xff0c;它在GitHub上免费提供。这个项目致力于收集和展示各类自由及开源软件&a…

“星战之父”乔治・卢卡斯吐槽好莱坞“几乎没有原创思维”,AI 将“不可避免”用于电影制作

《星球大战》系列的创作者乔治・卢卡斯&#xff08;George Lucas&#xff09;在 1977 年奠定了电影制作传奇人物的地位&#xff0c;他对当今电影的状况及其发展方向有一些自己的看法。 他在 2024 年戛纳电影节上谈到了当前的电影行业。现年 80 岁的卢卡斯在接受法国媒体 Brut …

rviz显示realsense点云卡顿问题的解决方法

rviz显示realsense点云卡顿问题的解决方法 问题描述解决方法方法一方法二PS 尚存疑惑 问题描述 在ubuntu20.04ros noetic下 使用realsense-ros 驱动&#xff0c;运行如下命令&#xff1a; roslaunch realsense2_camera rs_camera.launch filters:pointcloud使用rviz查看点云时…

Flutter 中的 AnimatedSize 小部件:全面指南

Flutter 中的 AnimatedSize 小部件&#xff1a;全面指南 在Flutter中&#xff0c;动画是增强用户界面和提供流畅用户体验的强大工具。AnimatedSize是一个用于动画化其子组件大小变化的组件&#xff0c;它可以在大小改变时添加动画效果&#xff0c;使得界面更加生动有趣。本文将…

C# 读取 CSV 文件的方法汇总

文章目录 1. 使用System.IO命名空间中的类2. 处理标题行和指定列3. 使用CsvHelper库4. 高级功能和异常处理5. 使用 LINQ6. 总结 CSV&#xff08;Comma-Separated Values&#xff0c;逗号分隔值&#xff09;文件是一种简单的文本文件格式&#xff0c;用于存储表格数据。在C#中&a…

微服务架构-数据共享设计模式

微服务架构-数据共享设计模式 每个微服务拥有自己的数据库&#xff0c;可以独立地进行数据库架构设计、部署和维护。这种是属于常规的方式&#xff0c;不受其他微服务的影响&#xff0c;具有高度的自治性。 然而&#xff0c;在将单体应用拆分成微服务时&#xff0c;可能会遇到…

QMetaObject::invokeMethod 简介

1. QMetaObject::invokeMethod的功能和用途 QMetaObject::invokeMethod是Qt框架中的一个功能强大的方法&#xff0c;它允许你以异步的方式调用QObject派生类的成员函数。这个功能特别有用&#xff0c;因为它允许你安全地在不同的线程之间调用方法&#xff0c;而不需要担心线程…

“盲人独立生活技能提升方案”:科技点亮希望之光

在追求平等与包容的社会进程中&#xff0c;盲人群体的独立生活能力提升成为了重要议题。随着科技的飞速发展&#xff0c;一款名为“蝙蝠避障”的辅助软件应运而生&#xff0c;以其独特的实时避障和拍照识别功能&#xff0c;为盲人在旅行乃至日常生活中开辟了新的可能。这不仅是…