Чтение онлайн

на главную - закладки

Жанры

QT 4: программирование GUI на С++

Саммерфилд Марк

Шрифт:

Если при выполнении приложения вы нажмете кнопку Start А, консоль заполнится буквами «А». Если вы нажмете кнопку Start В, консоль заполнится попеременно последовательностями букв «А» и «В». Нажмите кнопку Stop А, и тогда на экран будет выводиться только последовательность букв «В».

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

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

Класс QMutex обеспечивает

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

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

private:

QMutex mutex;

};

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

01 void Thread::run

02 {

03 forever {

04 mutex.lock;

05 if (stopped) {

06 stopped = false;

07 mutex.unlock;

08 break;

09 }

10 mutex.unlock;

11 cerr << qPrintable(messageStr.ascii);

12 }

13 cerr << endl;

14 }

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

01 void Thread::stop

02 {

03 mutex.lock;

04 stopped = true;

05 mutex.unlock;

06 }

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

01 void Thread::run

02 {

03 forever {

04 {

05 QMutexLocker locker(&mutex);

06 if (stopped) {

07 stopped = false;

08 break;

09 }

10 }

11 cerr << qPrintable(messageStr);

12 }

13 cerr << endl;

14 }

15 void Thread::stop

16 {

17 QMutexLocker locker(&mutex);

18 stopped = true;

18 }

Одна

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

В классе Thread не имеет смысла заменять мьютекс QMutex блокировкой QReadWriteLock для защиты переменной stopped, потому что в лучшем случае только один поток может пытаться читать эту переменную в любой момент времени. Более подходящий пример мог бы состоять из одного или нескольких считывающих потоков, получающих доступ к некоторым совместно используемым данным, и одного или нескольких записывающих потоков, модифицирующих данные. Например:

01 MyData data;

02 QReadWriteLock lock;

03 void ReaderThread::run

04 {

05 …

06 lock.lockForRead;

07 access_data_without_modifying_it(&data);

08 lock.unlock;

09 …

10 }

11 void WriterThread::run

12 {

13 …

14 lock.lockForWrite;

15 modify_data(&data);

16 lock.unlock;

17 …

18 }

Ради удобства мы можем использовать классы QReadLocker и QWriteLocker для блокировки и разблокировки объекта QReadWriteLock.

Класс QSemaphore — это еще одно обобщение мьютекса, но, в отличие от блокировок чтения/записи, он может использоваться для контроля некоторого количества идентичных ресурсов. Следующие два фрагмента программного кода демонстрируют соответствие между QSemaphore и QMutex:

Поделиться:
Популярные книги

Стеллар. Трибут

Прокофьев Роман Юрьевич
2. Стеллар
Фантастика:
боевая фантастика
рпг
8.75
рейтинг книги
Стеллар. Трибут

Его огонь горит для меня. Том 2

Муратова Ульяна
2. Мир Карастели
Фантастика:
юмористическая фантастика
5.40
рейтинг книги
Его огонь горит для меня. Том 2

На границе империй. Том 9. Часть 4

INDIGO
17. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 4

Наследник

Кулаков Алексей Иванович
1. Рюрикова кровь
Фантастика:
научная фантастика
попаданцы
альтернативная история
8.69
рейтинг книги
Наследник

Совершенно несекретно

Иванов Дмитрий
15. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Совершенно несекретно

Ваше Сиятельство 2

Моури Эрли
2. Ваше Сиятельство
Фантастика:
фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Ваше Сиятельство 2

Прометей: каменный век II

Рави Ивар
2. Прометей
Фантастика:
альтернативная история
7.40
рейтинг книги
Прометей: каменный век II

Единственная для темного эльфа 3

Мазарин Ан
3. Мир Верея. Драконья невеста
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Единственная для темного эльфа 3

Жандарм

Семин Никита
1. Жандарм
Фантастика:
попаданцы
альтернативная история
аниме
4.11
рейтинг книги
Жандарм

Долгий путь домой

Русич Антон
Вселенная EVE Online
Фантастика:
космическая фантастика
попаданцы
6.20
рейтинг книги
Долгий путь домой

Прогрессор поневоле

Распопов Дмитрий Викторович
2. Фараон
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Прогрессор поневоле

Наследие Маозари 6

Панежин Евгений
6. Наследие Маозари
Фантастика:
попаданцы
постапокалипсис
рпг
фэнтези
эпическая фантастика
5.00
рейтинг книги
Наследие Маозари 6

Я еще не барон

Дрейк Сириус
1. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я еще не барон

Лолита

Набоков Владимир Владимирович
Проза:
классическая проза
современная проза
8.05
рейтинг книги
Лолита