Qt之可重入与线程安全
简述
本篇文章中,术语“可重入性”和“线程安全”被用来标记类与函数,以表明它们如何被应用在多线程应用程序中。
一个线程安全的函数可以同时被多个线程调用,甚至调用者会使用共享数据也没有问题,因为对共享数据的访问是串行的。
一个可重入函数也可以同时被多个线程调用,但是每个调用者只能使用自己的数据。
因此,一个线程安全的函数总是可重入的,但一个可重入的函数并不一定是线程安全的。
扩展开来,一个可重入的类,指的是它的成员函数可以被多个线程安全地调用,只要每个线程使用这个类的不同的对象。而一个线程安全的类,指的是它的成员函数能够被多线程安全地调用,即使所有的线程都使用该类的同一个实例也没有关系。
注意: Qt的一些类被设计为线程安全的,如果它们的目的是多线程。如果一个函数没有被标记为线程安全的或可重入的,它就不应该被不同的线程使用。如果一个类没有被标记为线程安全的或可重入的,该类的实例就不应该被多个线程访问。
可重入性
C++的类往往是可重入的,这只是因为它们只能访问自己的数据。任何线程都能访问一个可重入类实例的一个成员函数,只要同一时间没有其它线程调用该实例的成员函数。例如,下面的Counter类就是可重入的:
class Counter
{
public:
Counter() { n = 0; }
void increment() { ++n; }
void decrement() { --n; }
int value() const { return n; }
private:
int n;
};
该类不是线程安全的,因为如果多个线程试图修改数据成员n,则结果是不确定的。这是因为++和–操作都不总是原子性的。事实上,它们一般被展开为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类在其构造函数中自动锁定mutex,并且当析构函数被调用时解锁。锁定mutex保证了其它线程的访问都将是串行化的。mutex数据成员被声明为mutable的,这是因为value()是一个const函数,我们需要在其中lock和unlock该mutex。
Qt类的注意事项
许多Qt的类都是可重入的,但不是线程安全的,因为线程安全意味着为锁定与解锁一个QMutex增加额外的开销。例如:QString是可重入的,但不是线程安全的。你能够同时从多个线程访问不同的QString的实例,但不能同时从多个线程访问QString的同一个实例(除非用QMutex保护访问)。
有些Qt的类和函数是线程安全的。它们主要是线程相关类(例如:QMutex)和一些基本函数(例如: QCoreApplication::postEvent())。
注意: 多线程领域中的术语并不是完全标准化的。POSIX使用的可重入和线程安全的定义有些不用于它的C API。当Qt和其它面向对象的C++类库一起使用时,确保定义的理解。
Qt之可重入与线程安全的更多相关文章
- Qt 进程和线程之三:线程同步、可重入与线程安全
一.同步线程方法 使用线程的目的是允许代码并行运行,但是有时线程必须停止并等待其他线程.例如,如果两个线程试图同时写入相同的变量,结果是不确定的,所以需要同步线程.同步线程是一种保护共享资源等数据的常 ...
- 可重入与线程安全(大多数Qt类是可重入,非线程安全的)
可重入与线程安全 在Qt文档中,术语“可重入”与“线程安全”被用来说明一个函数如何用于多线程程序.假如一个类的任何函数在此类的多个不同的实例上,可以被多个线程同时调用,那么这个类被称为是“可重入”的. ...
- Writing Reentrant and Thread-Safe Code(译:编写可重入和线程安全的代码)
Writing Reentrant and Thread-Safe Code 编写可重入和线程安全的代码 (http://www.ualberta.ca/dept/chemeng/AIX-43/sha ...
- 【C/C++】对于可重入、线程安全、异步信号安全几个概念的理解
由于前段时间,程序偶尔异常挂起不工作,检查后发现时死锁了,原因就是:在信号处理函数里面调用了fprintf. printf等io函数是需要对输出缓冲区加锁,这类函数对本身是线程安全的,但是对信号处理函 ...
- 可重入与线程安全(Reentrancy and Thread-Safety)
http://blog.csdn.net/zzwdkxx/article/details/49338067 http://blog.csdn.net/zzwdkxx/article/details/4 ...
- linux可重入、异步信号安全和线程安全
一 可重入函数 当一个被捕获的信号被一个进程处理时,进程执行的普通的指令序列会被一个信号处理器暂时地中断.它首先执行该信号处理程序中的指令.如果从信号处理程序返回(例如没有调用exit或longjmp ...
- 可重入函数、线程安全、volatile
一. POSIX 中对可重入和线程安全这两个概念的定义: Reentrant Function:A function whose effect, when called by two or more ...
- Linux 多线程可重入函数
Reentrant和Thread-safe 在单线程程序中,整个程序都是顺序执行的,一个函数在同一时刻只能被一个函数调用,但在多线程中,由于并发性,一个函数可能同时被多个函数调用,此时这个函数就成了临 ...
- linux: 可重入函数与不可重入函数
1. 可重入函数与线程安全 摘自 多线程和多进程的区别(小结) http://blog.csdn.net/hairetz/article/details/4281931 要确保函数线程安全,主要需要考 ...
随机推荐
- uTenux——重新整理底层驱动库
重新整理底层驱动库 1. 整理chip.h 在chip.h文件中的07----13的宏定义设置位如下,这样我们就不用在工程配中定义sam3s4c这个宏了,为我们以后通用少了一件麻烦事. //#if d ...
- linux 中 ll 命令如何让查询结果按时间升序或降序排序?
-t选项的功能是使输出的结果将以时间降序排列.如果希望按时间的升序排列,可以使用管道符将返回的结果传入tac命令.用法示例:查询当前目录的文件并以降序排列: ll -t查询当前目录的文件并以升序排列: ...
- HDU 5835 Danganronpa(弹丸论破)
Danganronpa(弹丸论破) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Other ...
- Android中的五大布局和logcat打印日志
在android中的布局有五大类,有的时候你可能用到一种,但有的时候你也可能需要两种或者三种布局同时一起使用.这五种布局为别为:LinearLayout(线性布局),FrameLayout(框架布局) ...
- 高并发简单解决方案————redis队列缓存+mysql 批量入库(ThinkPhP)
问题分析 问题一:要求日志最好入库:但是,直接入库mysql确实扛不住,批量入库没有问题,done.[批量入库和直接入库性能差异] 问题二:批量入库就需要有高并发的消息队列,决定采用redis lis ...
- iOS企业版打包(转载)
转自 http://www.cnblogs.com/shenlaiyaoshi/p/5472474.html 神来钥匙-陈诗友 iOS 企业版 打包 使用 iOS 企业版的证书发布应用可以跳过 A ...
- 关于css3的自定义字体
css3的@font-face属性打破了中文页面字体一成不变的格局,但今天本菜在用的时候并不那么爽.开始各种引用外部ttf文件失败.下了300M+的字体文件,苦逼的试了一下午.终于有一个ttf引用成功 ...
- poj3525Most Distant Point from the Sea(半平面交)
链接 求凸多边形内一点距离边最远. 做法:二分+半平面交判定. 二分距离,每次让每条边向内推进d,用半平面交判定一下是否有核. 本想自己写一个向内推进..仔细一看发现自己的平面交模板上自带.. #in ...
- poj1266Cover an Arc(三角形外接圆)
链接 求出三角形的外接圆,通过圆心和半径可以知道这个圆的上下左右最远点,分别判断这个四个点跟弧的两端点A,B的关系,假如判断P点,弧内给出点为C,判断PC是否与AB相交即可判断出P是否在弧上. 精度问 ...
- mysql 查询开销 sending data
1.执行一个查询,发现时间开销都在sending data,为什么?2.sending data容易误导,让人以为只是发送数据给客户端,实际上sending data包含两个过程:读取数据并处理,发送 ...