在一个程序中,这些独立运行的程序片断叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理”。多线程处理一个常见的例子就是用户界面。

QT 多线程程序之可重入与线程安全 是本节要介绍的内容,继续着 解析 QT 多线程程序详细设计 上篇 ,开始介绍。先来看内容。

解析 QT 多线程程序之可重入与线程安全 中篇(qt多进程与多线程)  多线程 线程安全 第1张

Qt文档中,术语“可重入”与“线程安全”被用来说明一个函数如何用于多线程程序。假如一个类的任何函数在此类的多个不同的实例上,可以被多个线程同时调用,那么这个类被称为是“可重入”的。假如不同的线程作用在同一个实例上仍可以正常工作,那么称之为“线程安全”的。

大多数c++类天生就是可重入的,因为它们典型地仅仅引用成员数据。任何线程可以在类的一个实例上调用这样的成员函数,只要没有别的线程在同一个实例上调用这个成员函数。举例来讲,下面的Counter 类是可重入的:

  1. classCounter{public:Counter(){
  2. n=0;
  3. }
  4. voidincrement(){
  5. ++n;
  6. }
  7. voiddecrement(){
  8. --n;
  9. }
  10. intvalue()const{
  11. returnn;
  12. }private:intn;
  13. };

这个类不是线程安全的,因为假如多个线程都试图修改数据成员 n,结果未定义。这是因为c++中的++和--操作符不是原子操作。实际上,它们会被扩展为三个机器指令:

1,把变量值装入寄存器

2,增加或减少寄存器中的值

3,把寄存器中的值写回内存

假如线程A与B同时装载变量的旧值,在寄存器中增值,回写。他们写操作重叠了,导致变量值仅增加了一次。很明显,访问应该串行化:A执行123步骤时不应被打断。使这个类成为线程安全的最简单方法是使用QMutex来保护数据成员:

  1. classCounter{public:Counter(){
  2. n=0;
  3. }
  4. voidincrement(){
  5. QMutexLockerlocker(&mutex);++n;
  6. }
  7. voiddecrement(){
  8. QMutexLockerlocker(&mutex);
  9. --n;
  10. }
  11. intvalue()const{
  12. QMutexLockerlocker(&mutex);
  13. returnn;
  14. }private:mutableQMutexmutex;
  15. intn;
  16. };

QMutexLocker类在构造函数中自动对mutex进行加锁,在析构函数中进行解锁。随便一提的是,mutex使用了mutable关键字来修饰,因为我们在value()函数中对mutex进行加锁与解锁操作,而value()是一个const函数。

大多数Qt类是可重入,非线程安全的。有一些类与函数是线程安全的,它们主要是线程相关的类,如QMutex,QCoreApplication::postEvent()。

线程与QObjects

QThread 继承自QObject,它发射信号以指示线程执行开始与结束,而且也提供了许多slots。更有趣的是,QObjects可以用于多线程,这是因为每个线程被允许有它自己的事件循环。

小结:QT 多线程程序之可重入与线程安全的内容介绍完了,希望本文能够对你有所帮助,如果你对本文感兴趣或者需要获得更多的资料,请参考

解析QT多线程程序详细设计之QObject可重入性 下篇。

转载请说明出处
知优网 » 解析 QT 多线程程序之可重入与线程安全 中篇(qt多进程与多线程)

发表评论

您需要后才能发表评论