Саммерфилд Марк
Шрифт:
В конструкторе мы вызываем функцию setMessage для периодического вывода на экран первым потоком буквы «А» и вторым потоком буквы «В».
Когда пользователь нажимает кнопку потока А, функция startOrStopThreadA останавливает поток, если он выполняется, и запускает его в противном случае. Она также обновляет текст кнопки.
Программный код функции startOrStopThreadB очень похож.
Если пользователь выбирает пункт меню Quit или закрывает окно, мы даем команду останова для каждого выполняющегося потока и ожидаем их завершения (используя функцию QThread::wait) прежде, чем сделать вызов CloseEvent::accept. Это обеспечивает аккуратный выход из приложения, хотя в данном случае это не имеет значения.
Если при выполнении приложения вы нажмете кнопку Start А, консоль заполнится буквами «А». Если вы нажмете кнопку Start В, консоль заполнится попеременно последовательностями букв «А» и «В». Нажмите кнопку Stop А, и тогда на экран будет выводиться только последовательность букв «В».
Синхронизация потоков
Обычным требованием для многопоточных приложений является синхронизация работы нескольких потоков. Для этого в Qt предусмотрены следующие классы: QMutex, QReadWriteLock, QSemaphore и QWaitCondition.
Класс QMutex обеспечивает такую защиту переменной или участка программного кода, что доступ к ним в каждый момент времени может осуществлять только один поток. Этот класс содержит функцию lock, которая закрывает мьютекс (mutex). Если мьютекс открыт, текущий поток захватывает его и немедленно закрывает; в противном случае работа текущего потока блокируется до тех пор, пока захвативший мьютекс поток не освободит его. В любом случае после вызова lock текущий поток будет держать мьютекс до вызова им функции unlock. Класс QMutex содержит также функцию tryLock, которая сразу же возвращает управление, если мьютекс уже закрыт.
Предположим, что нам нужно обеспечить защиту переменной stopped класса Thread из предыдущего раздела с помощью QMutex. Тогда мы бы добавили к классу Thread следующую переменную—член:
Функция run изменилась бы следующим образом:
Функция stop стала бы такой: