Qt扫盲-Reentrant和线程安全

这篇具有很好参考价值的文章主要介绍了Qt扫盲-Reentrant和线程安全。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、概述

在整个文档中, Reentrant 和 thread-safe 术语用于标记类和函数,指明如何在多线程应用程序中使用它们:

  • 一个 thread-safe的函数可以从多个线程同时调用,即使调用使用了共享数据,因为对共享数据的所有引用都是序列化的。
  • 一个 Reentrant 函数也可以从多个线程同时调用Reentrant函数,但前提是每次调用都使用自己的数据。

因此,thread-safe 的函数总是Reentrant的,但 Reentrant 的函数并不总是线程安全的,可以理解Reentrant 是线程不安全的。

扩展一下,如果一个类的成员函数可以在多个线程中安全地调用,只要每个线程使用这个类的不同实例,那么这个类就是Reentrant的。如果类的成员函数可以在多个线程中安全地调用,那么这个类就是线程安全的,即使所有线程都使用这个类的同一个实例。

注意:Qt类只有在被多个线程使用时才被记录为线程安全的。如果函数未标记为线程安全或Reentrant,则不应在不同的线程中使用它。如果类未标记为线程安全或Reentrant,则不应从不同线程访问该类的特定实例。

二、Reentrant

c++类通常是Reentrant的,因为它们只访问自己的成员数据。任何线程都可以调用Reentrant类实例的成员函数,只要其他线程不能同时调用同一个类实例的成员函数。例如,下面的Counter类是Reentrant的:

class Counter
{
  public:
      Counter() { n = 0; }

      void increment() { ++n; }
      void decrement() { --n; }
      int value() const { return n; }

  private:
      int n;
};

这个类不是线程安全的,因为如果多个线程试图修改数据成员n,结果是未定义的。这是因为 ++ 和 – 操作符并不总是原子的。实际上,它们通常扩展为3条机器指令:

  1. 将变量的值加载到寄存器中。
  2. 增加或减少寄存器的值。
  3. 将寄存器的值存储到主内存中。

如果线程A和线程B同时加载变量的旧值,增加它们的寄存器并存储它,它们最终会相互覆盖,变量只会增加一次!

三、线程安全

显然,访问必须序列化:线程A必须不间断地(原子操作的)执行步骤1、2、3,然后线程B才能执行相同的步骤;反之亦然。让类成为线程安全的一种简单方法是使用QMutex来保护对数据成员的所有访问:

class Counter
{
  public:
      Counter() { n = 0; }

      void increment() { QMutexLocker locker(&mutex); ++n; }
      void decrement() { QMutexLocker locker(&mutex); --n; }
      int value() const { QMutexLocker locker(&mutex); return n; }

  private:
      mutable QMutex mutex;
      int n;
};

QMutexLocker类会在构造函数中自动锁定互斥量,并在函数末尾调用析构函数时解锁。锁定互斥量可以确保来自不同线程的访问将被序列化。互斥量数据成员使用可变限定符声明,因为我们需要在value()中锁定和解锁互斥量,这是一个const函数。

四、Qt类的注意事项

许多Qt类是Reentrant的,但它们不是线程安全的,因为使它们成为线程安全的会导致重复锁定和解锁QMutex的额外开销。例如,QString是Reentrant的,但不是线程安全的。你可以从多个线程同时安全地访问不同的QString实例,但你不能从多个线程同时安全地访问同一个QString实例(除非你自己使用QMutex来保护访问)。

有些Qt类和函数是线程安全的。这些主要是线程相关的类(例如QMutex)和基本函数(例如QCoreApplication::postEvent())。文章来源地址https://www.toymoban.com/news/detail-422621.html

  • 注意:多线程领域的术语并没有完全标准化。POSIX使用的Reentrant和线程安全的定义与其C api有些不同。当在Qt中使用其他面向对象的c++类库时,请确保理解这些定义。

到了这里,关于Qt扫盲-Reentrant和线程安全的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Qt QQueue 安全的多线程队列、阻塞队列

    在C++中,queue是一个模板类,用于实现队列数据结构,遵循先进先出的原则。 ♦ 常用方法: · ♦ 简单使用: · ♦ 打印: · QQueue 继承与 QList ♦ 常用方法: · ♦ 实例: · ♦ 打印: · 在多线程编程中,由于QQueue并不是线程安全的,因此我们需要先使用互斥锁(QMutex)来保

    2024年02月16日
    浏览(36)
  • Unity扫盲:unity可以开多线程吗?

    在很多人的印象中,都觉得unity不支持多线程,因为里面有一个协程的概念,认为协程就是因为unity不支持多线程而用的一个功能,其实这是不对的,unity是可以开多线程的,只是一般不去开线程,为什么呢? 因为游戏大多数都是单线程,而且有的游戏对于GPU的要求比较高,大多数游戏考验

    2024年02月04日
    浏览(29)
  • Qt扫盲-Model/View入门

    每个UI开发人员都应该了解ModelView编程, 表格格控件、列表格控件和树控件是gui中经常使用的组件。这些控件有两种不同的方式访问它们的数据。 1.传统方法 传统的方法就是让控件本身去储存数据,在控件内部有数据容器,这种方法非常直观,但是,在许多重要的应用程序中

    2024年02月13日
    浏览(45)
  • Grafana技术文档-概念-《十分钟扫盲》 Grafana官网链接

    Grafana: The open observability platform | Grafana Labs Grafana是一个开源的度量分析和可视化套件,常用于对大量数据进行实时分析和可视化。以下是Grafana的基本概念: 数据源(Data Source):Grafana支持多种不同的时序数据库数据源,对每种数据源提供不同的查询方法,并能够很好地支持

    2024年02月13日
    浏览(42)
  • Qt之格栅布局(QGridLayout)控件填满整个单元格

    Qt专栏: 目录 1.现象1 2.解决方案 3.现象2 4.解决方案 5.总结         今天在用QGridLayout布局的时候,添加到布局的QWidget有文本框、标签、组合框和按钮等等,布局两列,通过下面的方式添加进去的: 发现在窗口拉伸的时候,pEdit 不会填满第0行1列的位置,右边有空隙。    

    2024年04月15日
    浏览(78)
  • Qt下Tcp套接字(socket)通信的整个流程

    QT += network Qt中提供的所有的Socket类都是非阻赛的 Qt中常用的用于socket通信的套接字类         QTcpServer 用于TCP/IP通信,作为服务器端套接字使用         QTcpSocket 用于TCP/IP通信,作为客户端套接字使用。         QUdpSocket 用于UDP通信,服务器,客户端均使用此套接字

    2024年02月10日
    浏览(31)
  • 《小白WEB安全入门》01. 扫盲篇

    本系列文章只叙述一些超级基础理论知识,极少有实践部分 web(World Wide Web)即全球广域网,也称为万维网,它是一种基于超文本和HTTP的、全球性的、动态交互的、跨平台的分布式图形信息系统。是建立在Internet上的一种网络服务,为浏览者在Internet上查找和浏览信息提供了

    2023年04月26日
    浏览(32)
  • [C++项目] Boost文档 站内搜索引擎(4): 搜索的相关接口的实现、线程安全的单例index接口、cppjieba分词库的使用、综合调试...

    有关 Boost 文档搜索引擎的项目的前三篇文章, 已经分别介绍分析了: 项目背景: 🫦[C++项目] Boost文档 站内搜索引擎(1): 项目背景介绍、相关技术栈、相关概念介绍… 文档解析、处理模块 parser 的实现: 🫦[C++项目] Boost文档 站内搜索引擎(2): 文档文本解析模块parser的实现、如何对

    2024年02月14日
    浏览(49)
  • Java多线程:进程与线程概述

    进程和线程 谈到多线程,就得先讲进程和线程的概念。 进程 进程可以理解为受操作系统管理的基本运行单元。360浏览器是一个进程、WPS也是一个进程,正在操作系统中运行的\\\".exe\\\"都可以理解为一个进程 线程 进程中独立运行的子任务就是一个线程。像QQ.exe运行的时候就有很

    2023年04月09日
    浏览(43)
  • 【线程池】概述及创建

    1.什么是线程池? 线程池就是一个可以复用线程的技术 2.不使用线程池的问题 用户每发起一个请求,后台就需要一个新的线程来处理,下次新的任务来了肯定又要创建新线程处理的,而创建新线程的开销是很大的,并且请求过多时,肯定会产生大量的线程出来,这样会严重影

    2024年02月09日
    浏览(20)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包