使用线程的目的是允许代码并行运行,但是有时线程必须停止并等待其他线程例如,如果两个线程试图同时写入相同的变量,结果是不确定的,所以需要同步线程同步线程是一种保护共享资源等数据的常见的技术迫使线程等待另一个的原则被称为互斥 ,今天小编就来说说关于qt线程怎么和主线通讯 Qt进程和线程之三?下面更多详细答案一起来看看吧!

qt线程怎么和主线通讯 Qt进程和线程之三

qt线程怎么和主线通讯 Qt进程和线程之三

1、同步线程方法

使用线程的目的是允许代码并行运行,但是有时线程必须停止并等待其他线程。例如,如果两个线程试图同时写入相同的变量,结果是不确定的,所以需要同步线程。同步线程是一种保护共享资源等数据的常见的技术。迫使线程等待另一个的原则被称为互斥 。

Qt 中的 QMutex、QReadWriteLock、QSemaphore 和 QWaitCondition 类提供了同步线程的方法。

2、可重入与线程安全

这里的术语“可重入性”和“线程安全”被用来标记类与函数,以表明它们如何被应用在多线程应用程序中。

因此,一个线程安全的函数总是可重入的,但一个可重入的函数并不一定是线程安全的。扩展开来,一个可重入的类,指的是它的成员函数可以被多个线程安全地调用,只要每个线程使用这个类的不同的对象。而一个线程安全的类,指的是它的成员函数能够被多线程安全地调用,即使所有的线程都使用该类的同一个实例也没有关系。

注意: 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条机器指令:

QT开发交流 赀料君羊:714620761

  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类在其构造函数中自动锁定mutex,并且当析构函数被调用时解锁。锁定mutex保证了其它线程的访问都将是串行化的。mutex数据成员被声明为mutable的,这是因为value()是一个const函数,我们需要在其中lock和unlock该mutex。

Qt类的注意事项

许多Qt的类都是可重入的,但不是线程安全的,因为线程安全意味着为锁定与解锁一个QMutex增加额外的开销。例如:QString是可重入的,但不是线程安全的。你能够同时从多个线程访问不同的QString的实例,但不能同时从多个线程访问QString的同一个实例(除非用QMutex保护访问)。

有些Qt的类和函数是线程安全的。它们主要是线程相关类(例如:QMutex)和一些基本函数(例如: QCoreApplication::postEvent())。

,