Qt多线程:使用互斥锁

1、官方文档:

QMutex类提供线程间的访问序列化。
QMutex的目的是保护一个对象、数据结构或代码片段, 
这样每次只有一个线程可以访问它(这类似于Java synchronized关键字)。 
通常最好将互斥对象与QMutexLocker一起使用,因为这样可以很容易地确保一致地执行锁定和解锁。

2、官方示例:

 QMutex mutex;
 int number = 6;

 void method1()
 {
     mutex.lock();
     number *= 5;
     number /= 4;
     mutex.unlock();
 }

 void method2()
 {
     mutex.lock();
     number *= 3;
     number /= 2;
     mutex.unlock();
 }

即使用户同时调用两个函数,在同一时刻,也只会执行一个函数内操作number的代码。

3、配合QMutexLocker使用

单独使用QMutex时,每次都需要加锁、解锁,显得不太方便,QMutex配合QMutexLocker使用是比较推荐的方法:
头文件:

#include  
...
private:
    QMutex _mutex;
...

同一个例子:使用QMutexLocker极大地简化了代码,并使其更具可读性:

 QMutex mutex;
 int number = 6;

 void method1()
 {
     QMutexLocker locker(&_mutex);
     number *= 5;
     number /= 4;
 }

 void method2()
 {
	 QMutexLocker locker(&_mutex);
     number *= 3;
     number /= 2;
 }

现在,当QMutexLocker对象被销毁时(当函数返回时,locker是一个自动变量)互斥锁总是会被解锁。
同样的原理也适用于抛出和捕获异常的代码。锁定互斥锁的函数中没有捕获到的异常在将异常传递到调用函数之前无法解锁互斥锁。
QMutexLocker还提供了一个mutex()成员函数,该函数返回QMutexLocker正在操作的互斥对象。这对于需要访问互斥锁的代码很有用,比如QWaitCondition::wait()。

关于Qt线程同步,还有其他更多可以参考的:

QMutex 是强制执行互斥的基本类。一个线程锁定一个互斥量(mutex),以获得共享资源的访问权限。如果另一个线程试图锁定互斥量,而互斥量已被锁定,这时,它将进入睡眠状态,直到第一个线程完成其任务并解锁互斥量。

QReadWriteLock 类似于 QMutex,除了它区分了“读”和“写”的访问。当一个数据块没有被写入,多线程对他同时进行读取是安全的。一个 QMutex 迫使轮流读取共享数据,而 QReadWriteLock 允许同时读取,从而提高并行性。

QSemaphore 是 QMutex 的一个推广,可以保护一定数量相同的资源。相比之下,一个 QMutex 只能保护一个资源。Qt之线程同步(生产者消费者模式 - QSemaphore) 提供了一个典型的案例,信号量:在“生产者 - 消费者”之间同步访问循环缓冲区。

QWaitCondition 同步线程,不通过执行互斥,而通过提供一个条件变量。其它原语使线程等待,直到资源被解锁;QWaitCondition 使线程等待,直到满足一个特定的条件。让等待中的线程继续进行,调用 wakeOne() 来唤醒一个随机选择的线程或 wakeAll() 同时唤醒所有。Qt之线程同步(生产者消费者模式 - QWaitCondition) 显示了如何使用 QWaitCondition 代替 QSemaphore 来实现“生产者 - 消费者”模式。

这些同步类可以用来使一个方法线程安全。然而,这样做会带来性能损失,这就是为什么大多数 Qt 方法不是线程安全的。

QMutex、QSemaphore与QReadWriteLock
QWaitCondition 的正确使用方法
Qt 之线程同步

你可能感兴趣的:(QT)