类似java的synchronized(同步)关键字,QMutex的目的是保护一个对象、数据结构体或者一部分代码。
一次只允许一个线程访问被保护对象。QMutexLocker总能帮助通常使用去控制一个mutex。
因为它总能确保锁定和解锁很好地被执行。
例如,下面是一条用两行的代码向用户打印出一个消息的函数:
int number = 6;
void method1()
{
number *= 5;
number /= 4;
}
void method2()
{
number *= 3;
number /= 2;
}
若这两条函数都调用成功,结果如下:
// method1()
number *= 5; // number是30
number /= 4; // number是7
// method2()
number *= 3; // number是21
number /= 2; // number是10
若这两条函数同时被两个线程调用,按以下顺序,结果如下:
// 线程 1调用 method1()
number *= 5; // number是30
// 线程2调用method2().
//
// 系统让线程1休眠
// 系统让线程2运行
number *= 3; // number四90
number /= 2; // number是45
// 线程1完成执行
number /= 4; // number是11,而不是10
若添加一个互斥体(mutex),结果才符合预期
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,结果就是正确的。
当然,上面是个没意义的例子。但是解决方案适用于任何需要按照特定队列执行的情况。
在某个线程中调用lock()锁定后,其他线程在相同位置调用lock()后就会一直阻塞,直到得到锁的线程调用Unlock()。
非阻塞锁定是tryLock()。
QMutex能在无争议地方优化,若一个地方没有争议,QMutex就不会为互斥体(mutex)分配空间。
此时,QMutex的构造和析构没有任何开销,这就意味着,在其他类中,内含很多个互斥体(mutexs)没有任何问题。
QMutex::Recursive
1
该模式下,单个线程能够锁定同一个互斥体多次,只有对应个数的unlock()被调用,互斥体才会解锁
QMutex::NonRecursive
0
该模式下,单个线程只能锁定一个互斥体一次。
See also QMutex().