Spec-Zone.ru › Qt 5.6

Класс QMutex

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

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

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

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

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

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

QMutex(RecursionMode mode = NonRecursive)
bool isRecursive()
void lock()
bool tryLock(int timeout = 0)
void unlock()

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

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

Цель 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 оптимизирован для скорости в случае отсутствия конфликтов. Нерекурсивный QMutex не будет выделять память, если нет конфликтов по этому мьютексу. Он создаётся и уничтожается практически без накладных расходов, что означает, что можно иметь множество мьютексов в качестве части других классов.

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

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

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

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

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

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

QMutex::QMutex(RecursionMode mode = NonRecursive)

Создаёт новый мьютекс. Мьютекс создаётся в разблокированном состоянии.

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

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

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

bool QMutex::isRecursive()

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

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

void QMutex::lock()

Блокирует мьютекс. Если другой поток заблокировал мьютекс, этот вызов будет блокироваться, пока этот поток не разблокирует его.

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

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

bool QMutex::tryLock(int timeout = 0)

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

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

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

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

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

void QMutex::unlock()

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

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

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

Spec-Zone.ru

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