Spec-Zone.ru › Qt 5.15

Класс QMutex

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

Заголовок: #include <QMutex>
qmake: QT += core
Наследуется от:

QRecursiveMutex

  • Список всех членов, включая унаследованные

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

Открытые типы

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

Открытые функции

QMutex(QMutex::RecursionMode mode)
QMutex()
~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 предназначен для защиты объекта, структуры данных или фрагмента кода, чтобы к нему одновременно мог получить доступ только один поток (это аналогично ключевому слову 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 как части других классов допустимо.

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

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

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

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

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

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

QMutex::QMutex(QMutex::RecursionMode mode)

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

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

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

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

QMutex::QMutex()

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

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.

template <typename Rep, typename Period> 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().

template <typename Clock, typename Duration> 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.15/qmutex.html

Spec-Zone.ru

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