Книги
чёрным по белому
Главное меню
Главная О нас Добавить материал Поиск по сайту Карта книг Карта сайта
Книги
Археология Архитектура Бизнес Биология Ветеринария Военная промышленность География Геология Гороскоп Дизайн Журналы Инженерия Информационные ресурсы Искусство История Компьютерная литература Криптология Кулинария Культура Лингвистика Математика Медицина Менеджмент Металлургия Минералогия Музыка Научная литература Нумизматика Образование Охота Педагогика Политика Промышленные производства Психология Путеводители Религия Рыбалка Садоводство Саморазвитие Семиотика Социология Спорт Столярное дело Строительство Техника Туризм Фантастика Физика Футурология Химия Художественная литература Экология Экономика Электроника Энергетика Этика Юриспруденция
Новые книги
Цуканов Б.И. "Время в психике человека" (Медицина)

Суворов С. "Танк Т-64. Первенец танков 2-го поколения " (Военная промышленность)

Нестеров В.А. "Основы проэктирования ракет класса воздух- воздух и авиационных катапульных установок для них" (Военная промышленность)

Фогль Б. "101 вопрос, который задала бы ваша кошка своему ветеринару если бы умела говорить" (Ветеринария)

Яблоков Н.П. "Криминалистика" (Юриспруденция)
Реклама

C++. Энциклопедия пользователя - Либерти Дж.

Либерти Дж. C++. Энциклопедия пользователя — Москва, 2001. — 581 c.
Скачать (прямая ссылка): enciklopediyapolzovatelya2001.djvu
Предыдущая << 1 .. 52 53 54 55 56 57 < 58 > 59 60 61 62 63 64 .. 280 >> Следующая

Теперь func2() вызывает функцию Updater(), которая выполняется снова, на этот раз в контексте потока 2. Она получает ту же самую запись (случайно), обновляет ее, прежде чем прерывается.
Затем возобновляется поток 1, и функция Updater() продолжает выполнение с того места, где она была прервана, с записью, которая была изначально считана из базы данных. Запись будет обновлена и записана обратно. При этом будут искажены обновления, произведенные в потоке 2.
Это один пример из многих, когда многопоточность может исказить данные, если применяемые методы не являются потокобезопасными.
Краткий совет по поводу многопоточности: если можно избежать написания многопоточного кода, то избегайте его. Не используйте многопоточность до тех пор, пока есть иной выбор. Многопоточность делает код сложным и гораздо более трудным для поддержки. Она существенно увеличивает вероятность ошибок и чаще всего снижает производительность. В конце концов, она занимает время на обработку контекста потока и переключение потоков. Добавьте достаточно потоков, и процессор будет тратить значительную часть времени, просто переключаясь между ними, и пропорционально этому меньше времени будет тратиться на выполнение полезной работы!
Предположим, что имеется программа, которая принимает много данных, высчитывает сумму и затем использует эту сумму во втором уравнении. "Ага! — скажете вы. — Две задачи! Я создам два потока". Проблема в том, что второй поток не может начинаться до тех пор, пока не закончит работу первый. Даже если вы можете вычислять их в одно и то же время и если нельзя использовать данные до тех пор, пока оба не завершатся, то почему бы не выполнять их последовательно, а не параллельно? Выполнение задач вместе не даст ничего, а цена переключения между задачами может быть слишком высока.
Итак, когда же использовать многопоточность? Классический сценарий — это когда одна задача занимает много времени, а вторая задача не зависит от первой. Предположим, что необходимо сохранить данные на жестком диске и также отобразить их на экране. Вам не нравится ждать, пока данные будут сохраняться на жестком диске и лишь потом появятся на экране, — запись на диск может продлиться долго. Почему бы не поместить задачу "запись на диск" в отдельный поток и не запустить более важную задачу взаимодействия с пользователем? Действительно, почему бы нет?
Пример для изучения
Автор написал приложение, которое "звонит" по телефону. Это напоминает те раздражающие телемар-кетинговые звонки, которые звучат, когда вы сидите за ужином. Разница заключается в том, что эта программа "звонит" только тем, кто желает принимать звонки. Программа полностью автоматизирована и "не звонит" во время ужина.
Компьютер может звонить 72 разным людям одновременно. После каждого звонка программа сохраняет результаты вызова и периодически обновляет базу данных полученными результатами. Одновременно она хранит кэш номеров для вызова, так чтобы никогда не простаивать. Данный проект связан с многопоточностью.
Конструкция проекта довольно сложна, но наша цель — прийти к следующему: автор запускает один поток для каждой линии вызова (CCaller) для 72 потоков, если все 72 линии активны. Автор также создал один поток для управления отчетом о функционировании (Creporter) и еще один поток для управления набором звонков, ожидающих освобождения линии (CLocalCallQueue). Наконец, есть главный поток, который управляет всеми другими потоками и который владеет пользовательским интерфейсом (панелью управления наблюдением за звонками). Таким образом, приложение выполняет 75 потоков!
Это большое число потоков, но при наличии мощного компьютера (Windows NT Workstation, выполняющейся на компьютере с процессором Pentium PC, и 128 Мб оперативной памяти) они работают дос-
Использование каркасов приложении 1 ПС
Глава 5 ¦ 1 Zj
таточно быстро, создавая иллюзию одновременности работы. Кроме того, приложение само не только многопоточное, но и многопроцессное, поскольку существуют дополнительные вызывающие устройства и дополнительные компоненты в других процессах (и на других устройствах), ответственные за планирование заданий и управление базой данных.
Теперь рассмотрим проблемы, которые возникают в подобной среде.
Создание потоков
Первая задача состоит в создании потока. Фактически существует два разных способа создания и управления потоками. Первый подходит для использования с элементами (окнами), которые должны выполняться как поток. Представьте объект, который содержит методы, но оперирует ими независимо от всех других потоков. Это первый тип потока, и он порождается от класса CWinThread.
Второй тип потока более подходит для использования в том случае, когда необходима функция, выполняющаяся в собственном потоке. На такой тип потока ссылаются как на рабочий.
Использование объектов CWinThread
Объект CWinThread создается точно так же, как любой другой объект: вы порождаете его от самого CWinThread или от какого-то класса, который порожден от CWinThread. Когда реализуется CWinThread-порождённый объект, то поток не создается. Для создания потока необходимо вызвать метод CreateThreadQ данного объекта.
Предыдущая << 1 .. 52 53 54 55 56 57 < 58 > 59 60 61 62 63 64 .. 280 >> Следующая