Синхронизация потоков

Обычным требованием для многопоточных приложений является синхрониза­ция работы нескольких потоков. Для этого в Qt предусмотрены следующие классы: QMutex, QReadWriteLock, QSemaphore и QWaitCondition.

Класс QMutex обеспечивает такую защиту переменной или участка программного кода, что доступ к ним в каждый момент времени может осуществлять только один поток. Этот класс содержит функцию 1оск(), которая закрывает мьютекс (mutex). Если мьютекс открыт, текущий поток захватывает его и немедленно закрывает; в противном случае работа текущего потока блокируется до тех пор, пока захватив­ший мьютекс поток не освободит его. В любом случае после вызова 1оск() текущий поток будет держать мьютекс до вызова им функции unlock(). Класс QMutex содер­жит также функцию t ryl_ock(), которая сразу же возвращает управление, если мью­текс уже закрыт.

Предположим, что нам нужно обеспечить защиту переменной stopped класса Thread из предыдущего раздела с помощью QMutex. Тогда мы бы добавили к классу Thread следующую переменную-член:

private:

QMutex mutex;

};

Функция run() изменилась бы следующим образом:

void Thread::run() {

forever {

mutex.lock(); if (stopped) {

stopped = false;

mutex.unlock();

break;

}

mutex.unlock();

cerr « qPrintable(messageStr.ascii); }

cerr « endl; }

Функция stop() стала бы такой:

void Thread::stop() {

mutex.lock(); stopped = true; mutex.unlock();

}

Блокировка и разблокировка мьютекса в сложных функциях или там, где обра­батываются исключения С++, может иметь ошибки. Qt предлагает удобный класс QMutexLocker, упрощающий обработку мьютексов. Конструктор QMutexLocker при­нимает в качестве аргумента объект QMutex и блокирует его. Деструктор QMutexLocke г разблокирует мьютекс. Например, мы могли бы приведенные выше функции гип() и stop() переписать следующим образом:

void Thread::run() {

forever { {

QMutexLocker locker(&mutex); if (stopped) {

stopped = false;

break;

}

}

cerr « qPrintable(messageStr);

}

cerr « endl;

}

void Thread::stop() {

QMutexLocker locker(&mutex); stopped = true;

}

Одна из проблем применения мьютексов возникает из-за доступности перемен­ной только для одного потока. В программах со многими потоками, пытающимися одновременно читать одну и ту же переменную (не модифицируя ее), мьютекс мо­жет серьезно снижать производительность


<< назад вперед >>