Класс QMutex
Класс QMutex обеспечивает сериализацию доступа между потоками. Подробнее...
| Заголовок: | #include <QMutex> |
| CMake: | find_package(Qt6 COMPONENTS Core REQUIRED) target_link_libraries(mytarget PRIVATE Qt6::Core) |
| qmake: | QT += core |
Примечание: Все функции в этом классе являются безопасными для потоков.
Открытые функции
| QMutex() | |
| ~QMutex() | |
| void | lock() |
| 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.
Документация по функциям-членам
QMutex::QMutex()
Создаёт новый мьютекс. Мьютекс создаётся в разблокированном состоянии.
QMutex::~QMutex()
Уничтожает мьютекс.
Предупреждение: Уничтожение заблокированного мьютекса может привести к неопределённому поведению.
void QMutex::lock()
Блокирует мьютекс. Если другой поток заблокировал мьютекс, этот вызов будет блокироваться до тех пор, пока этот поток не разблокирует его.
Вызов этой функции несколько раз для одного и того же мьютекса из одного и того же потока приведёт к тупиковой ситуации.
См. также unlock().
bool QMutex::tryLock(int timeout)
Пытается заблокировать мьютекс. Эта функция возвращает true, если блокировка была получена; в противном случае она возвращает false. Если другой поток заблокировал мьютекс, эта функция будет ждать не более timeout миллисекунд, пока мьютекс станет доступным.
Примечание: Передача отрицательного числа в качестве timeout эквивалентна вызову lock(), т. е. эта функция будет ждать вечно, пока мьютекс не будет заблокирован, если timeout отрицательный.
Если блокировка была получена, мьютекс должен быть разблокирован с помощью unlock() перед тем, как другой поток сможет успешно заблокировать его.
Вызов этой функции несколько раз для одного и того же мьютекса из одного и того же потока приведёт к тупиковой ситуации.
bool QMutex::tryLock()
Это перегруженная функция.
Пытается заблокировать мьютекс. Эта функция возвращает true если блокировка была получена; в противном случае она возвращает false.
Если блокировка была получена, мьютекс должен быть разблокирован с помощью unlock() перед тем, как другой поток сможет успешно заблокировать его.
Вызов этой функции несколько раз для одного и того же мьютекса из одного и того же потока приведёт к тупиковой ситуации.
[since 5.8] bool QMutex::try_lock()
Пытается заблокировать мьютекс. Эта функция возвращает true если блокировка была получена; в противном случае она возвращает false.
Эта функция предоставляется для совместимости с концепцией Стандартной библиотеки Lockable. Она эквивалентна tryLock().
Эта функция была введена в Qt 5.8.
[since 5.8] template <typename Rep, typename Period> bool QMutex::try_lock_for(std::chrono::duration<Rep, Period> duration)
Пытается заблокировать мьютекс. Эта функция возвращает true если блокировка была получена; в противном случае она возвращает false. Если другой поток заблокировал мьютекс, эта функция будет ждать не менее duration, пока мьютекс станет доступным.
Примечание: Передача отрицательной длительности в качестве duration эквивалентно вызову try_lock(). Это поведение отличается от tryLock().
Если блокировка была получена, мьютекс должен быть разблокирован с помощью unlock() перед тем, как другой поток сможет успешно заблокировать его.
Вызов этой функции несколько раз для одного и того же мьютекса из одного и того же потока приведёт к тупиковой ситуации.
Эта функция была введена в Qt 5.8.
[since 5.8] 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() перед тем, как другой поток сможет успешно заблокировать его.
Вызов этой функции несколько раз для одного и того же мьютекса из одного и того же потока приведёт к тупиковой ситуации.
Эта функция была введена в Qt 5.8.
void QMutex::unlock()
Разблокирует мьютекс. Попытка разблокировать мьютекс в другом потоке, отличном от потока, который его заблокировал, приводит к ошибке. Разблокировка мьютекса, который не заблокирован, приводит к неопределённому поведению.
См. также lock().
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.0/qmutex.html