Spec-Zone.ru › Qt 5.9

Класс QMutex

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

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

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

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

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

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

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()
  • 6 функций публичного доступа, унаследованных от QBasicMutex

Подробное описание

Класс 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(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.9/qmutex.html

Spec-Zone.ru

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