Spec-Zone.ru › Qt 5.12

Класс QMutex

Класс QMutex обеспечивает сериализацию доступа между потоками. Подробнее...

Заголовок: #include <QMutex>
qmake: QT += core
Наследуется от: QBasicMutex
  • Список всех членов, включая наследуемые

Примечание: Все функции в этом классе являются безопасными для многопоточного доступа.

Типы публичного доступа

перечисление RecursionMode { Recursive, NonRecursive }

Функции публичного доступа

QMutex(QMutex::RecursionMode mode = NonRecursive)
~QMutex()
bool isRecursive() const
void lock()
bool tryLock(int timeout = 0)
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 обеспечивает сериализацию доступа между потоками.

Класс QMutex предназначен для защиты объекта, структуры данных или блока кода, чтобы к нему мог обращаться только один поток одновременно (это аналогично ключевому слову Java synchronized). Обычно лучше использовать mutex с 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

Если мы добавим 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(). Неблокирующая альтернатива lock() — это tryLock().

QMutex оптимизирован для высокой скорости в случае отсутствия конкуренции. Нерекурсивный QMutex не будет выделять память, если на этом mutex нет конкуренции. Он создаётся и уничтожается практически без накладных расходов, что означает, что иметь много mutex как часть других классов допустимо.

См. также QMutexLocker, QReadWriteLock, QSemaphore и QWaitCondition.

Документация по типам членов

перечисление QMutex::RecursionMode

Константа Значение Описание
QMutex::Recursive 1 В этом режиме поток может заблокировать один и тот же mutex несколько раз, и mutex не будет разблокирован до тех пор, пока не будет выполнено соответствующее количество вызовов unlock().
QMutex::NonRecursive 0 В этом режиме поток может заблокировать mutex только один раз.

См. также QMutex().

Документация по функциям-членам

QMutex::QMutex(QMutex::RecursionMode mode = NonRecursive)

Создаёт новый mutex. Mutex создаётся в разблокированном состоянии.

Если mode равно QMutex::Recursive, поток может заблокировать один и тот же mutex несколько раз, и mutex не будет разблокирован до тех пор, пока не будет выполнено соответствующее количество вызовов unlock(). В противном случае поток может заблокировать mutex только один раз. По умолчанию — QMutex::NonRecursive.

Рекурсивные mutex медленнее и занимают больше памяти, чем нерекурсивные.

См. также lock() и unlock().

QMutex::~QMutex()

Уничтожает mutex.

Предупреждение: Уничтожение заблокированного mutex может привести к неопределённому поведению.

bool QMutex::isRecursive() const

Возвращает true, если mutex рекурсивный.

Функция была добавлена в Qt 5.7.

void QMutex::lock()

Заблокировать mutex. Если другой поток заблокировал mutex, этот вызов будет заблокирован до тех пор, пока этот поток не разблокирует его.

Вызов этой функции несколько раз на том же mutex из одного и того же потока разрешен, если этот mutex является рекурсивным mutex. Если этот mutex — нерекурсивный mutex, эта функция вызовет зависание при рекурсивной блокировке mutex.

См. также unlock().

bool QMutex::tryLock(int timeout = 0)

Попытка заблокировать mutex. Эта функция возвращает true если блокировка была получена; в противном случае она возвращает false. Если другой поток заблокировал mutex, эта функция будет ждать не более timeout миллисекунд, пока mutex не станет доступным.

Примечание: Передача отрицательного числа в качестве timeout эквивалентна вызову lock(), т.е. эта функция будет ждать вечно, пока mutex не будет заблокирован, если timeout отрицательный.

Если блокировка была получена, mutex необходимо разблокировать с помощью unlock() перед тем, как другой поток сможет успешно заблокировать его.

Вызов этой функции несколько раз на одном и том же mutex из одного и того же потока разрешен, если этот mutex является рекурсивным mutex. Если этот mutex — нерекурсивный mutex, эта функция всегда вернёт false при попытке рекурсивной блокировки mutex.

См. также lock() и unlock().

bool QMutex::try_lock()

Попытка заблокировать mutex. Эта функция возвращает true если блокировка была получена; в противном случае она возвращает false.

Эта функция предоставляется для совместимости с концепцией Стандартной библиотеки Lockable. Она эквивалентна tryLock().

Функция возвращает true если блокировка была получена; в противном случае возвращает false

Функция была добавлена в Qt 5.8.

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

Попытка заблокировать mutex. Эта функция возвращает true если блокировка была получена; в противном случае она возвращает false. Если другой поток заблокировал mutex, эта функция будет ждать не менее duration, пока mutex не станет доступным.

Примечание: Передача отрицательной длительности в качестве duration эквивалентна вызову try_lock(). Это поведение отличается от tryLock().

Если блокировка была получена, mutex необходимо разблокировать с помощью unlock() перед тем, как другой поток сможет успешно заблокировать его.

Вызов этой функции несколько раз на одном и том же mutex из одного и того же потока разрешен, если этот mutex является рекурсивным mutex. Если этот mutex — нерекурсивный mutex, эта функция всегда вернёт false при попытке рекурсивной блокировки mutex.

Функция была добавлена в Qt 5.8.

См. также lock() и unlock().

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

Попытка заблокировать mutex. Эта функция возвращает true если блокировка была получена; в противном случае она возвращает false. Если другой поток заблокировал mutex, эта функция будет ждать не менее времени, указанного в timePoint, пока mutex не станет доступным.

Примечание: Передача значения timePoint, которое уже прошло, эквивалентно вызову try_lock(). Это поведение отличается от tryLock().

Если блокировка была получена, mutex необходимо разблокировать с помощью unlock() перед тем, как другой поток сможет успешно заблокировать его.

Вызов этой функции несколько раз для одного и того же мьютекса в одном и том же потоке разрешен, если этот мьютекс является рекурсивным мьютексом. Если этот мьютекс является нерекурсивным мьютексом, эта функция всегда вернёт false при попытке рекурсивной блокировки мьютекса.

Эта функция была добавлена в Qt 5.8.

См. также lock() и unlock().

void QMutex::unlock()

Разблокирует мьютекс. Попытка разблокировать мьютекс в другом потоке, нежели тот, который его заблокировал, приведёт к ошибке. Разблокировка мьютекса, который не заблокирован, приведёт к неопределённому поведению.

См. также lock().

© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.12/qmutex.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API