本页内容

QMutex Class

QMutex 类提供了线程之间的访问序列化。更多内容...

头文件: #include <QMutex>
CMake: find_package(Qt6 REQUIRED COMPONENTS Core)
target_link_libraries(mytarget PRIVATE Qt6::Core)
qmake: QT += core

注意:该类中的所有函数均是线程安全的。

公共函数

QMutex()
~QMutex()
void lock()
(since 6.6) bool tryLock(QDeadlineTimer timer)
bool tryLock(int timeout)
bool tryLock()
bool try_lock()
bool try_lock_for(std::chrono::duration<Rep, Period> duration)
bool try_lock_until(std::chrono::time_point<Clock, Duration> timePoint)
void unlock()

详细说明

QMutex 的目的是保护一个对象、数据结构或代码段,以便每次只有一个线程可以访问它(这类似于 Java 中的 `synchronized ` 关键字)。通常最好将互斥量与 `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 。

成员函数文档

[constexpr noexcept default] QMutex::QMutex()

创建一个新的互斥锁。该互斥锁创建时处于未锁定状态。

[noexcept] QMutex::~QMutex()

销毁互斥锁。

警告:销毁 被锁定的互斥锁可能会导致未定义的行为。

[noexcept(...)] void QMutex::lock()

锁定互斥锁。如果另一个线程已经锁定了该互斥锁,则此调用将阻塞,直到该线程解锁为止。

如果互斥锁已被当前线程锁定,则此调用将永远不会返回,从而导致死锁。

注意: 当FutexAlwaysAvailable 为true 时,此 函数为noexcept。

另请参阅 unlock()。

[noexcept(...), since 6.6] bool QMutex::tryLock(QDeadlineTimer timer)

尝试锁定互斥锁。如果成功获得锁,该函数返回true ;否则返回false 。如果另一个线程已锁定该互斥锁,该函数将等待直至timer 超时,以使互斥锁变得可用。

如果成功获取了锁,必须先使用unlock() 解锁互斥锁,其他线程才能成功锁定它。

该函数在 Qt 6.6 中引入。

注意: 当FutexAlwaysAvailable 为true 时,此 函数为 noexcept。

另请参阅 lock() 和unlock()。

[noexcept(...)] bool QMutex::tryLock(int timeout)

尝试锁定互斥量。如果成功获得锁,该函数返回true ;否则返回false 。如果另一个线程已锁定该互斥量,该函数将最多等待timeout 毫秒,直到互斥量可用。

注意:将负数作为timeout 参数传递等同于调用lock(),即如果timeout 为负数,则该函数将无限期等待,直到能够锁定互斥锁为止。

如果获得了锁,则必须先使用unlock() 解锁互斥锁,另一个线程才能成功锁定它。

注意: 当FutexAlwaysAvailable 为true 时,此 函数为 noexcept。

另请参见 lock() 和unlock()。

[noexcept] bool QMutex::tryLock()

尝试锁定互斥锁。如果成功获得锁,该函数返回true ;否则返回false 。

如果成功获取了锁,则必须先通过unlock() 解锁互斥锁,其他线程才能成功锁定它。

这是一个重载函数。

另请参阅 lock() 和unlock()。

[noexcept] bool QMutex::try_lock()

尝试锁定互斥锁。如果成功获取锁,该函数返回true ;否则返回false 。

提供此函数是为了与标准库中的Lockable 概念保持兼容。它等同于tryLock()。

template <typename Rep, typename Period> bool QMutex::try_lock_for(std::chrono::duration<Rep, Period> duration)

尝试锁定互斥量。如果成功获得锁,该函数返回true ;否则返回false 。如果另一个线程已锁定该互斥量,该函数将至少等待duration ,直到互斥量可用。

注意:将负数作为duration 参数传递,等同于调用try_lock()。此行为与tryLock()不同。

如果成功获取了锁,则必须先使用unlock() 解锁互斥锁,其他线程才能成功锁定它。

另请参阅 lock() 和unlock()。

template <typename Clock, typename Duration> bool QMutex::try_lock_until(std::chrono::time_point<Clock, Duration> timePoint)

尝试锁定互斥量。如果成功获得锁,该函数返回true ;否则返回false 。如果另一个线程已锁定该互斥量,该函数将至少等待timePoint ,直到互斥量可用为止。

注意:传递一个已过期的timePoint 等同于调用try_lock()。此行为与tryLock()不同。

如果已获取锁,则必须先使用unlock() 解锁互斥锁,其他线程才能成功锁定它。

另请参阅 lock() 和unlock()。

[noexcept] void QMutex::unlock()

解锁互斥锁。若尝试在与锁定该互斥锁不同的线程中解锁,将引发错误。解锁未被锁定的互斥锁将导致未定义行为。

另请参阅 lock()。

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.