QMutex类提供线程之间的访问序列化。
头文件:
#include <QMutex>cmake:
find_package(Qt6 COMPONENTS Core REQUIRED) target_link_libraries(mytarget PRIVATE Qt6::Core)qmake:
QT += core
详细说明
QMutex的目的是保护对象、数据结构或者代码段,以便每次只有一个线程可以访问它(这类似于Java synchronized关键字)。通常最好将QMutex和QMutexLocker一起使用,因为这样可以很容易的确保锁定和解锁一致的执行。
比如,有一个方法用两行向用户输出信息:
int number = 6;
void method1()
{
number *= 5;
number /= 4;
}
void method2()
{
number *= 3;
number /= 2;
}
如果这两个方法被连续调用,会发生以下情况:
// method1()
number *= 5; // number is now 30
number /= 4; // number is now 7
// method2()
number *= 3; // number is now 21
number /= 2; // number is now 10
如果这两个方法同时在两个线程中调用,那么结果可能如下:
// Thread 1 calls method1()
number *= 5; // number is now 30
// Thread 2 calls method2().
//
// Most likely Thread 1 has been put to sleep by the operating
// system to allow Thread 2 to run.
number *= 3; // number is now 90
number /= 2; // number is now 45
// Thread 1 finishes executing.
number /= 4; // number is now 11, instead of 10
如果我们添加了一个互斥锁,就会得到我们想要的结果:
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()。lock()的非阻塞替代方法是tryLock()。
QMutex经过优化,在非争用情况下速度更快。如果没有争用这个互斥锁,它将不会分配内存。它的构造和销毁几乎没有任何开销,这意味着将许多互斥对象作为其他类的一部分是可以的。
参见QRecursiveMutex、QMutexLocker、QReadWriteLock、QSemaphore和QWaitCondition。
成员函数
QMutex
QMutex::QMutex()
构造一个新的互斥锁。互斥锁是在未锁定状态创建的。
~QMutex
QMutex::~QMutex()
破坏了互斥锁。
警告:销毁一个锁定的互斥锁可能会导致未定义的行为。
lock
void QMutex::lock()
锁定互斥锁。如果另一个线程锁定了互斥锁,那么这个调用将会阻塞,直到该线程解锁了互斥锁。
在同一个线程的同一个互斥锁上多次调用这个函数将导致死锁。
tryLock
bool QMutex::tryLock(int timeout)
试图锁定互斥锁。如果获得了锁,这个函数返回true;否则返回false。如果另一个线程锁定了互斥锁,这个函数将等待最多毫秒的超时时间,以使互斥锁可用。
注意:传递一个负数作为timeout相当于调用lock(),也就是说,如果timeout为负数,这个函数将永远等待直到互斥锁被锁定。
如果获得了锁,那么在其他线程成功锁定互斥对象之前,必须先使用unlock()解除锁定。
在同一个线程的同一个互斥锁上多次调用这个函数将导致死锁
bool QMutex::tryLock()
这是一个重载函数。
试图锁定互斥锁。如果获得了锁,这个函数返回true;否则返回false。
如果获得了锁,那么在其他线程成功锁定互斥对象之前,必须先使用unlock()解除锁定。
在同一个线程的同一个互斥锁上多次调用这个函数将导致死锁。
try_lock
bool QMutex::try_lock()
试图锁定互斥锁。如果获得了锁,这个函数返回true;否则返回false。
提供这个函数是为了兼容标准库的概念可锁。它相当于tryLock()。
这个函数是在Qt 5.8中引入的。
try_lock_for
[since 5.8]
template <typename Rep, typename Period> bool QMutex::try_lock_for(std::chrono::duration<Rep, Period> duration)
试图锁定互斥锁。如果获得了锁,这个函数返回true;否则返回false。如果另一个线程锁定了互斥锁,这个函数将至少等待互斥锁可用的时间。
注意:传递负的持续时间相当于调用try_lock()。这种行为与tryLock()不同。
如果获得了锁,那么在其他线程成功锁定互斥对象之前,必须先使用unlock()解除锁定。
在同一个线程的同一个互斥锁上多次调用这个函数将导致死锁。
这个函数是在Qt 5.8中引入的。
请参阅lock()和unlock()。
try_lock_until
[since 5.8]
template <typename Clock, typename Duration> bool QMutex::try_lock_until(std::chrono::time_point<Clock, Duration> timePoint)
试图锁定互斥锁。如果获得了锁,这个函数返回true;否则返回false。如果另一个线程锁定了互斥锁,这个函数将至少等待到互斥锁可用的时间点。
注意:传递一个已经传递的时间点等同于调用try_lock()。这种行为与tryLock()不同。
如果获得了锁,那么在其他线程成功锁定互斥对象之前,必须先使用unlock()解除锁定。
在同一个线程的同一个互斥锁上多次调用这个函数将导致死锁。
这个函数是在Qt 5.8中引入的。
unlock
void QMutex::unlock()
解除互斥锁。试图解锁另一个线程中的互斥锁,而锁定互斥锁的线程会导致错误。解锁未锁定的互斥锁将导致未定义的行为。