Читаем QT 4: программирование GUI на С++ полностью

Семафор freeSpace управляет той частью буфера, которая может заполняться потоком, формирующим данные. Семафор usedSpace управляет той областью, которую может считывать поток—приемник. Эти две области взаимно дополняют друг друга. Семафор freeSpace устанавливается на значение переменной BufferSize (4096), то есть он может захватывать именно такое количество ресурсов. Когда приложение запускается, поток, считывающий данные, начинает захватывать «свободные» байты и превращать их в «используемые» байты. Семафор usedSpace инициализируется нулевым значением, чтобы поток—приемник не мог считать «мусор» при запуске приложения.

В этом примере каждый байт рассматривается как один ресурс. В реальном приложении мы, вероятно, использовали бы более крупные блоки памяти (например, по 64 или 256 байт) для снижения затрат, обусловленных применением семафоров.

01 void Producer::run()

02 {

03 for (int i = 0; i < DataSize; ++i) {

04 freeSpace.acquire();

05 buffer[i % BufferSize] = "ACGT"[uint(rand()) % 4];

06 usedSpace.release();

07 }

08 }

Каждая итерация при работе потока, формирующего данные, начинается с захвата одного «свободного» байта. Если весь буфер заполнен данными, которые не считаны потоком—приемником, вызов функции acquire() заблокирует семафор до тех пор, пока поток—приемник не начнет считывать данные. Захватив байт, мы заполняем его некоторым случайным значением («А», «С», «G» или «T») и затем освобождаем байт и помечаем его как «использованный», тем самым указывая на возможность его считывания потоком—приемником.

01 void Consumer::run()

02 {

03 for (int i = 0; i < DataSize; ++i) {

04 usedSpace.acquire();

05 cerr << buffer[i % BufferSize];

06 freeSpace.release();

07 }

08 cerr << endl;

09 }

Работу потока—приемника мы начинаем с захвата одного «использованного» байта. Если буфер не содержит данных для чтения, вызов функции acquire() заблокирует семафор до тех пор, пока первый поток не сформирует какие-то данные. После захвата нами байта мы выводим его на экран и освобождаем байт, помечая его как «свободный», тем самым позволяя первому потоку вновь присвоить ему некоторое значение.

01 int main()

02 {

03 Producer producer;

04 Consumer consumer;

05 producer.start();

06 consumer.start();

07 producer.wait();

08 consumer.wait();

09 return 0;

10 }

Наконец, в функции main() мы запускаем оба потока. После этого происходит следующее: поток, формирующий данные, преобразует некоторое «свободное» пространство в «использованное», после чего поток—приемник может выполнить его обратное преобразование в «свободное» пространство.

Когда программа выполняется, она выводит на консоль случайную последовательность из 100 000 букв «А», «С», «G» и «T» и затем завершает свою работу. Для того чтобы понять, что происходит на самом деле, мы можем отключить вывод указанной последовательности и вместо этого выводить на консоль букву «P» при генерации каждого байта первым потоком и букву «с» при чтении байта вторым потоком. И ради максимального упрощения ситуации мы можем использовать меньшие значения параметров DataSize и BufferSize.

Например, при выполнении программы, когда DataSize равен 10 и BufferSize равен 4, результат может быть таким: «PcPcPcPcPcPcPcPcPcPc». В данном случае поток—приемник считывает байты сразу по мере их формирования первым потоком; оба потока работают на одной скорости. В другом случае первый поток может заполнять буфер целиком еще до начала его считывания вторым потоком: «PPPPccccPPPPccccPPcc». Существует много других вариантов. Семафоры дают большую свободу действий планировщикам потоков в специфических системах, что позволяет им, изучив поведение потоков, выбрать подходящую политику планирования их работы.

Другой подход к решению проблемы синхронизации работы потока, формирующего данные, и потока, принимающего данные, состоит в применении классов QWaitCondition и QMutex. Класс QWaitCondition позволяет одному потоку «пробуждать» другие потоки, когда удовлетворяется некоторое условие. Этим обеспечивается более точное управление, чем путем применения только одних мьютексов. Чтобы показать, как это работает, мы переделаем пример с двумя потоками, используя условия ожидания.

const int DataSize = 100000;

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных