QT 多线程程序之可重入与线程安全 是本节要介绍的内容,继续着 解析 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,结果未定义。这是因为c++中的++和--操作符不是原子操作。实际上,它们会被扩展为三个机器指令:
1,把变量值装入寄存器
2,增加或减少寄存器中的值
3,把寄存器中的值写回内存
假如线程A与B同时装载变量的旧值,在寄存器中增值,回写。他们写操作重叠了,导致变量值仅增加了一次。很明显,访问应该串行化:A执行123步骤时不应被打断。使这个类成为线程安全的最简单方法是使用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使用了mutable关键字来修饰,因为我们在value()函数中对mutex进行加锁与解锁操作,而value()是一个const函数。
大多数Qt类是可重入,非线程安全的。有一些类与函数是线程安全的,它们主要是线程相关的类,如QMutex,QCoreApplication::postEvent()。
线程与QObjects
QThread 继承自QObject,它发射信号以指示线程执行开始与结束,而且也提供了许多slots。更有趣的是,QObjects可以用于多线程,这是因为每个线程被允许有它自己的事件循环。
小结:QT 多线程程序之可重入与线程安全的内容介绍完了,希望本文能够对你有所帮助,如果你对本文感兴趣或者需要获得更多的资料,请参考