for (i=0 ; i<5 ; i++) t[i].wait() ; //дождаться завершения дочерних потоков
for (i=0,rez=0 ; i<6 ; i++) rez+=C[i] ; //найти скалярное произведение
fprintf(stdout,"Скалярное произведение = %d", rez) ;
return 1 ;
}
Обратите внимание на то, что каждый поток осуществляет запись,
исключительно в выделенные для него элементы массива, индексы которых не
пересекаются для различных потоков. Это связано с тем, что возможность
изменения одних и тех же данных несколькими потоками является критической
секцией многопоточной алгоритма и может привести к возникновению ошибок.
Такая критическая секция должна быть защищена семафором.
Многопоточное приложение и графический интерфейс
Работа с графическим интерфейсом возможна только в родительском
процессе, попытка обратиться к любому элементу графического интерфейса из
потока приведет к ошибке. Кроме этого в порожденных потоках не следует
производить следующие действия, т.к. они могут привести к аварийному
завершению программы. Создание объектов классов QWidget (и классов-
потомков), QTimer, QSocketNotifier, QSocket, QServerSocket. Использование
объектов классов QSocket и QServerSocket. Запуск или остановка таймера.
Вызов функции setEnabled класса QSocketNotifier. Вызов функции exec. Вызов
функции-обработчика события. В порожденном потоке можно использовать
механизм сигналов и слотов и уведомлять объект о событии.
Перепишем последний пример, создав графический интерфейс. Результат
работы потоков выведем в поле ввода lineEdit1, по нажатию на кнопку
pushButton1 будут запускаться потоки. Вывод результата будет производиться
процессом-родителем по наступлению события.
События представлены классом QEvent, а также дочерними классами,
такими как, QTimerEvent, QMouseEvent, QKeyEvent, QPaintEvent, QMoveEvent,
QResizeEvent, QShowEvent, QHideEvent и т.д. Все вышеперечисленные классы
описывают стандартные события, тогда как для использования в потоках,
целесообразнее использовать события определяемые программистом. Для этого
существует класс QCustomEvent.
102