Какие приложения используют многопоточность процессора

Обновлено: 06.07.2024

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

Давайте начнем с основных понятий: ядер центрального процессора, компьютерных процессов и потоков, а затем попробуем понять преимущества многопоточного программирования.

Компьютерный процесс в сравнении с потоком

Проще говоря, процесс — это программа в ходе своего выполнения . Когда мы выполняем программу или приложение, запускается процесс. Каждый процесс состоит из одного или нескольких потоков.

Поток — это не что иное, как сегмент процесса . Потоки — исполняемые сущности, которые выполняют задачи, стоящие перед исполняемым приложением. Процесс завершается, когда все потоки заканчивают выполнение .

Роль ядер процессора

Каждый поток в процессе — это задача, которую должен выполнить процессор. Большинство процессоров сегодня умеют выполнять одновременно две задачи на одном ядре, создавая дополнительное виртуальное ядро. Это называется одновременная многопоточность или многопоточность Hyper-Threading, если речь о процессоре от Intel. Эти процессоры называются многоядерными процессорами. Таким образом, двухъядерный процессор имеет 4 ядра: два физических и два виртуальных. Каждое ядро может одновременно выполнять только один поток .

Почему многопоточность?

Как упоминалось выше, один процесс содержит несколько потоков, и одно ядро процессора может выполнять только один поток за единицу времени. Если мы пишем программу, которая запускает потоки последовательно, то есть передает выполнение в очередь одного конкретного ядра процессора, мы не раскрываем весь потенциал многоядерности. Остальные ядра просто стоят без дела, в то время как существуют задачи, которые необходимо выполнить. Если мы напишем программу таким образом, что она создаст несколько потоков для отнимающих много времени независимых функций, то мы сможем использовать другие ядра процессора, которые в противном случае пылились бы без дела. Можно выполнять эти потоки параллельно, тем самым сократив общее время выполнения процесса.

Время запачкать руки

Мы напишем программу, где запустим две функции (выполним две задачи). Сначала мы будем выполнять функции последовательно, через один и тот же поток, а затем создадим отдельные потоки для каждой из них. При этом отметим время выполнения для обоих подходов и увидим кое-что волшебное:

Summation1 и Summation2 — это два класса-заглушки, которые нам нужно выполнить. На их месте может быть любая бизнес-логика, которую вам захочется реализовать. Я только добавил случайные циклы, чтобы увеличить время выполнения — это поможет лучше продемонстрировать результаты:

каковы некоторые конкретные примеры приложений, которые должны быть многопоточными или не должны быть, но намного лучше?

ответы были бы лучше, если в виде одного приложения на пост таким образом, наиболее применимые будут плавать к вершине.

нет жесткого и быстрого ответа, но большую часть времени вы не увидите никаких преимуществ для систем, где процесс расчета состоит в последовательном. Если, однако, проблема может быть разбита на задачи, которые могут выполняться параллельно (или сама проблема массово параллельна [как некоторые математические или аналитические задачи]), вы можете увидеть большие улучшения.

Если ваше целевое оборудование-один процессор / ядро, вы вряд ли увидите какие-либо улучшения с многопоточным решения (так как в любом случае есть только один поток за раз!)

писать многопоточный код часто сложнее, так как вам может потребоваться инвестировать время в создание логики управления потоками.

сервера обычно многопоточны (веб-серверы, серверы radius, серверы электронной почты, любой сервер): вы обычно хотите иметь возможность обрабатывать несколько запросов одновременно. Если вы не хотите ждать окончания запроса, прежде чем начать обрабатывать новый запрос, то у вас в основном есть два варианта:

  1. запустить процесс с несколькими потоками
  2. запустить несколько процессов

запуск процесса обычно более ресурсоемкий чем lauching поток (или выбор одного в пуле потоков), поэтому серверы обычно многопоточны. Кроме того, потоки могут взаимодействовать напрямую, поскольку они имеют одинаковое пространство памяти.

проблема с несколькими потоками заключается в том, что их обычно сложнее правильно кодировать, чем несколько процессов.

есть действительно три класса причин, по которым будет применяться многопоточность:

  • параллелизм выполнения для повышения производительности вычислений: если у вас есть проблема, которая может быть разбита на части, и у вас также есть более одного блока выполнения (ядро процессора), то отправка частей в отдельные потоки-это путь к возможности одновременного использования двух или более ядер одновременно.
  • параллелизм CPU и IO Операции: это похоже на мышление первого, но в этом случае цель состоит в том, чтобы держать процессор занят, а также операции ввода-вывода (т. е. дисковый ввод-вывод), движущиеся параллельно, а не чередующиеся между ними.
  • дизайн программы и отзывчивость: многие типы программ могут воспользоваться преимуществами потоковой обработки в качестве преимущества дизайна программы, чтобы сделать программу более отзывчивой к пользователю. Например, программа может взаимодействовать через GUI, а также делать что-то в фон.
  • Microsoft Word: редактирование документа в то время как фон грамматики и проверки орфографии работает, чтобы добавить все зеленые и красные подчеркивания закорючки.
  • Microsoft Excel: автоматические перерасчеты фона после редактирования ячейки
  • Браузер: отправка нескольких потоков для загрузки каждой из нескольких ссылок HTML параллельно во время загрузки одной страницы. Ускоряет загрузку страниц и максимизирует пропускную способность данных TCP/IP.

в эти дни, ответ должен быть любое приложение, которое может быть.

скорость выполнения для одного потока в значительной степени достигла пика много лет назад - процессоры становятся быстрее, добавляя ядра, а не увеличивая тактовую частоту. Были некоторые архитектурные улучшения, которые лучше используют доступные тактовые циклы, но на самом деле будущее использует преимущества резьбы.

существует тонна исследований, направленных на поиск путей распараллеливание действий, которые мы традиционно не думали бы распараллеливать. Даже такая простая вещь, как поиск подстроки внутри строки, может быть распараллелена.

в основном есть две причины для многопоточности:

чтобы иметь возможность выполнять задачи обработки параллельно. Это применимо только в том случае, если у вас несколько ядер/процессоров, иначе на одном компьютере с ядром/процессором вы замедлите задачу по сравнению с версией без потоков.

I/O будь то сетевой ввод-вывод или файловый ввод-вывод.обычно, если вы вызываете блокировку вызова ввода-вывода, процесс должен ждать завершения вызова. Поскольку процессор / память на несколько порядков быстрее, чем дисковод (а сеть еще медленнее), это означает, что процессор будет ждать долгое время. Компьютер будет работать над другими вещами, но ваше приложение не будет делать никакого прогресса. Однако, если у вас несколько потоков, компьютер будет планировать ваше приложение, а другие потоки могут выполняться. Одним из распространенных применений является приложение GUI. Затем, пока приложение выполняет ввод-вывод, поток GUI может продолжать обновлять экран, не глядя, как приложение заморожено или не отвечает. Даже на одном процессоре ввод/вывод в другой поток будет способствовать ускорению работы приложения.

однопоточная Альтернатива 2 - использовать асинхронные вызовы, когда они возвращаются немедленно, и вы продолжаете контролировать свою программу. Затем вы должны увидеть, когда ввод-вывод завершается и управлять его использованием. Часто проще просто использовать поток для ввода-вывода, используя синхронные вызовы, как они имеют тенденцию быть легче.

причина использования потоков вместо отдельных процессов заключается в том, что потоки должны иметь возможность обмениваться данными проще, чем несколько процессов. И иногда переключение между потоками дешевле, чем переключение между процессами.

многие рамки GUI многопоточны. Это позволяет вам иметь более отзывчивый интерфейс. Например, вы можете нажать на кнопку "Отмена" в любое время, пока выполняется длинный расчет.

обратите внимание, что есть и другие решения для этого (например, программа может приостанавливать расчет каждые полсекунды, чтобы проверить, нажали ли вы на кнопку отмены или нет), но они не предлагают тот же уровень отзывчивости (GUI может показаться, замерзнуть на несколько секунд во время чтения файла или выполнения вычисления).

все ответы до сих пор сосредоточены на том, что многопоточность или многопоточность необходимы для оптимального использования современного оборудования.

существует, однако, и тот факт, что многопоточность может сделать жизнь намного проще для программиста. На работе я программирую программное обеспечение для управления производственным и испытательным оборудованием, где одна машина часто состоит из нескольких параллельно работающих позиций. Использование нескольких потоков для такого программного обеспечения является естественным, поскольку параллельные нити довольно хорошо моделируют физическую реальность. Потокам в основном не нужно обмениваться данными, поэтому необходимость синхронизации потоков встречается редко, и поэтому многие из причин сложности многопоточности не применяются.

Edit:

на самом деле речь идет не об улучшении производительности, поскольку (возможно, 5, Возможно, 10) потоки в основном спят. Однако это огромное улучшение для структуры программы, когда различные параллельные процессы могут быть закодированы как последовательности действий, которые не знают друг друга. У меня очень плохие воспоминания со времен 16-битных окон, когда я создавал государственную машину для каждой позиции машины, убеждался, что ничего не займет больше нескольких миллисекунд, и постоянно передавал управление следующей государственной машине. Когда были аппаратные события, которые нужно было обслуживать вовремя, а также вычисления, которые заняли некоторое время (например, FFT), тогда все будет очень быстро.

не отвечая непосредственно на ваш вопрос, я считаю, что в ближайшем будущем почти каждое приложение должно быть многопоточным. Производительность процессора не растет так быстро в эти дни, что компенсируется увеличение количества ядер. Таким образом, если мы хотим, чтобы наши приложения оставались на вершине производительности, нам нужно найти способы использовать все процессоры вашего компьютера и держать их занятыми, что довольно сложная работа.

пожалуйста, примите это как дополнительную информацию для размышления, а не как попытку ответить на ваш вопрос.

вид приложений, которые нужно быть продетым нитку одни где вы хотите делать больше чем одну вещь сразу. Кроме этого, ни одно приложение не должно быть многопоточным.

применения с большой рабочей нагрузкой которую можно легко сделать параллельной. Трудность принятия Вашего заявления и делать это не следует недооценивать. Легко, когда ваши данные, которыми вы манипулируете, не зависят от других данных, но v. трудно запланировать работу перекрестного потока, когда есть зависимость.

некоторые примеры, которые я сделал, которые являются хорошими кандидатами многопоточный..

  • запущенные сценарии (например, цены на производные акции, статистика)
  • массовое обновление файлов данных (например, добавление значения / записи в 10 000 записей)
  • другие математические процессы

например, вы хотите, чтобы ваши программы были многопоточными, когда вы хотите использовать несколько ядер и/или процессоров, даже если программы не обязательно сделайте много вещей в то же время.

EDIT: использование нескольких процессов-одно и то же. Какой метод использовать, зависит от платформы и того, как вы собираетесь делать коммуникации в рамках своей программы и т. д.

хотя фривольные, игры, в общем, становятся все более и более резьбовыми с каждым годом. На работе наша игра использует около 10 потоков, занимающихся физикой, AI, анимацией, Редингом, сетью и IO.

просто хочу добавить, что необходимо соблюдать осторожность с протекторами, если ваш общий доступ к каким-либо ресурсам может привести к очень странному поведению, и ваш код работает неправильно или даже потоки, блокирующие друг друга.

мьютекс поможет вам там, поскольку вы можете использовать блокировки мьютекса для защищенных областей кода, примером защищенных областей кода будет чтение или запись в общую память между потоками.

только мои 2 цента стоит.

основная цель многопоточность для разделения временных доменов. Таким образом, использование везде, где вы хотите, чтобы несколько вещей произошли в их собственных отчетливо отдельных временных областях.

Нет, это статья не о харкоде или ассемблере.
Решая вопрос о необходимости апгрейда, я исследовал некоторые игры и бенчмарки. Нашел кое-что интересное, чем и хочу поделиться с общественностью.
Текста и лирики будет много, но вы сами научитесь анализировать не только игру, но и любое приложение на предмет многопоточности.

Хотелось бы предупредить, что я не программист или разработчик, а потому могу ошибаться в деталях. Но в целом, я уверен, что все понял и описал правильно. Уверен, что на конечный вывод мои мелкие ошибки или заблуждения существенно не повлияют. Все мысли и выводы, изложенные в этой статье, являются сугубо моим личным мнением, составленным по материалам из сети. Если вам показалось, что я где-то кого-то в чем-то обвинил, то это следует считать моим личным, субьективным, мнением.
Поехали…
Конфигурация:
Монитор: Plasma TV 42" Panasonic, 1280x720, HDMI
Процессор: AMD Phenom II X4 925 (TPD 95W) 2.8 ГГц @ 3.5 ГГц при 1.48v.
Материнская плата: Asus M4N72-E Socket AM2+ / AM3 ( nForce 750a SLI )
Охлаждение: CM Hyper 212+ PWM
Оперативная память: 4x2Gb DDR2-800@833 при 1.9v (5-5-5-23)
Видеокарта: MSI 460 GTX HAWK 1GB 780/3600 @ 900/4000 x 2 в SLI 8х+8х
HDD:Crucial M4 128Gb + WD 500Gb + WD1500Gb
Блок питания: Chieftec APS-850C
Корпус:Corsair Carbide Series 200R

Все началось с желания апгрейда. Большой мальчик закапризничал и захотел новую игрушку, хотя и старая не плохая.
Голос из зала: «Детей тебе делать и растить надо, а не играть в эти твои компьютеры».
Изучая множество тестов, выбор ГПУ особого труда не занял — SLI 660/660ti, в зависимости от уровня финансов в период совершения покупки.
Вопрос с ЦПУ и платформой оказался сложнее. Осложняла его в основном «жаба».
Intel выходил дороже и заметно. Как раз на разницу SLI 660 vs SLI 660ti.
Желание поддержать AMD сталкивалось с печалью от получения меньшего FPS и его просадок в играх. С AMD я терял часть производительности будущей, довольно мощной SLI системы (разумеется в сравнении с имеющейся SLI).
В поисках решения куда же идти и что делать, я начал проверять как обстоят дела у игр с многопотоком.

Суровые реалии.


Мне нужен многоядерный AMD или скорострельный, словно специально «запиленный» для «кривого» софта, Intel?
Решая этот вопрос, «выкуривая» тесты и играясь с бенчмарками, я вдруг получил такую картину:

( увеличенное изображение)
Это бенчмарк Heaven 4, запущенный под OpenGL при минимальных настройках, в окне 800х600.
Как видите FPS составляет

113 кадров. Казалось бы, бенчмарк это синтетика, должна уметь ВСЕ выжимать из ПК.
Но обратите внимание, что загрузка ЦПУ около 50%, причем заняты все ядра.
MSI Afterburner показывает, что видеокарты загружены на

Спустя пару дней вечернего чтения и экспериментов виновные были найдены. Их оказалось двое.
1. Windows.
2. Разработчик приложения.
Да, да, внезапно, но Windows опять виноват. Нет, это не кривая установка, поломанная ОСь или что-то подобное.
Это «бага», которая даже не «бага», а вовсе даже «фича».
Здесь банальное введение пользователя в заблуждение диспетчером задач и планировщиком процессов.
Сейчас расскажу и покажу, что происходит на самом деле. Разберем ситуацию на примере бенчмарка Heaven.
Что такое многопоточное приложение?
Это приложение, процесс, который может инициировать несколько потоков обработки данных. Эти потоки называются thread (нить, поток).
Потоки эти не из параллельного мира и их вполне можно пощупать и увидеть с помощью специальных инструментов.
Нам понадобится:

20-23% времени ЦПУ, чем съедали около 65-70% его ресурсов, и два-три мелких потока по 2-5%. Последние за потоки можно было бы и не считать, но три потока по 5% это 15%, а на ядро у нас приходится 25%. В итоге можно сказать, что Crysis 3 и Battlefield 3 хорошо оптимизированы для 4х ядер и способных с хорошей эффективностью их нагрузить, а вот большее количество ядер им поможет слабо.Темп прироста FPS от количества ядер свыше 4 — будет снижен. Собственно тесты Core 2gen/3gen vs FX Vishera это и показывают.

Спасибо, что дочитали до конца. Удачи Вам.

Смотрим на траву.

( увеличенное изображение)
1024x768, High, noAA, 16AF, Vsync OFF
Смотрим в небо.

( увеличенное изображение)


Смотрим на траву.

( увеличенное изображение)
Я написал апдейт статьи только из-за последнего скрина.
На нем видно, что процесс Crysis 3 инициировал 7 потоков обработки и почти на

100% загрузил все 4 ядра ЦПУ.
Ранее он такое поведение не обнаруживал.
Таким образом, вывод об оптимизации в статье следует сделать несколько иной:
Crysis 3 способен загрузить работой как минимум 6 ядер ЦПУ, а, учитывая мелкие треды, скорее всего работы хватит и 8 ядрам. Единственное что — такие броски и нагрузки случаются не всегда и в этой игре встречаются только в местах с травой. В корридорах нагрузка на ЦПУ слабая.
Недавно Лаборатория провела тест ЦПУ и ГПУ как раз в этой же локации.
Как видим Vishera ее 8 ядер не сильно и помогли. Она может тягаться только на равных с i5 без индекса К.
А когда i5 с индексом К соревнуется с ней на равной частоте, то i5 уходит в заметный отрыв.
Phenom II x4 частотой 3.5 ГГц не достаточно для комфортной игры потому, что нагрузка на ЦПУ запредельная, а в случае игрового «замеса» в этой локации ФПС упадет еще сильнее, ниже 20. Можно немного снизить зависимость от ЦПУ, если выставить дальность анимации травы через консоль — e_MergedMeshesInstanceDist 2 (по-умолчанию 4.5 / 8 ). Это поднимет FPS на десяток кадров.
ps. На скришотах OSD информация в игре о ЦПУ и ГПУ получена с помощью Play Claw 4.
Создана тема по сбору статистики в играх!!

UPD 16.07.2015: Из статьи была удалена информация и домыслы о компиляторах.


Какая тема вызывает больше всего вопросов и затруднений у начинающих? Когда я спросила об этом преподавателя и Java-программиста Александра Пряхина, он сразу ответил: «Многопоточность». Спасибо ему за идею и помощь в подготовке этой статьи!

Мы заглянем во внутренний мир приложения и его процессов, разберёмся, в чём суть многопоточности, когда она полезна и как её реализовать — на примере Java. Если учите другой язык ООП, не огорчайтесь: базовые принципы одни и те же.

О потоках и их истоках

Чтобы понять многопоточность, сначала вникнем, что такое процесс. Процесс – это часть виртуальной памяти и ресурсов, которую ОС выделяет для выполнения программы. Если открыть несколько экземпляров одного приложения, под каждый система выделит по процессу. В современных браузерах за каждую вкладку может отвечать отдельный процесс.

Вы наверняка сталкивались с «Диспетчером задач» Windows (в Linux это — «Системный монитор») и знаете, что лишние запущенные процессы грузят систему, а самые «тяжёлые» из них часто зависают, так что их приходится завершать принудительно.

Но пользователи любят многозадачность: хлебом не корми — дай открыть с десяток окон и попрыгать туда-сюда. Налицо дилемма: нужно обеспечить одновременную работу приложений и при этом снизить нагрузку на систему, чтобы она не тормозила. Допустим, «железу» не угнаться за потребностями владельцев — нужно решать вопрос на программном уровне.

Мы хотим, чтобы в единицу времени процессор успевал выполнить больше команд и обработать больше данных. То есть нам надо уместить в каждом кванте времени больше выполненного кода. Представьте единицу выполнения кода в виде объекта — это и есть поток.

К сложному делу легче подступиться, если разбить его на несколько простых. Так и при работе с памятью: «тяжёлый» процесс делят на потоки, которые занимают меньше ресурсов и скорее доносят код до вычислителя (как именно — см. ниже).

У каждого приложения есть как минимум один процесс, а у каждого процесса — минимум один поток, который называют главным и из которого при необходимости запускают новые.

Разница между потоками и процессами

Потоки используют память, выделенную под процесс, а процессы требуют себе отдельное место в памяти. Поэтому потоки создаются и завершаются быстрее: системе не нужно каждый раз выделять им новое адресное пространство, а потом высвобождать его.

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

Какой отсюда вывод? Если вам нужно как можно быстрее обработать большой объём данных, разбейте его на куски, которые можно обрабатывать отдельными потоками, а затем соберите результат воедино. Это лучше, чем плодить жадные до ресурсов процессы.

Но почему такое популярное приложение как Firefox идёт по пути создания нескольких процессов? Потому что именно для браузера изолированная работа вкладок — это надёжно и гибко. Если с одним процессом что-то не так, не обязательно завершать программу целиком — есть возможность сохранить хотя бы часть данных.

Что такое многопоточность

Вот мы и подошли к главному. Многопоточность — это когда процесс приложения разбит на потоки, которые параллельно — в одну единицу времени — обрабатываются процессором.

Вычислительная нагрузка распределяется между двумя или более ядрами, так что интерфейс и другие компоненты программы не замедляют работу друг друга.

Многопоточные приложения можно запускать и на одноядерных процессорах, но тогда потоки выполняются по очереди: первый поработал, его состояние сохранили — дали поработать второму, сохранили — вернулись к первому или запустили третий, и т.д.


Занятые люди жалуются, что у них всего две руки. Процессы и программы могут иметь столько рук, сколько нужно для скорейшего выполнения задачи.

Жди сигнала: синхронизация в многопоточных приложениях

Представьте, что несколько потоков пытаются одновременно изменить одну и ту же область данных. Чьи изменения будут в итоге приняты, а чьи — отменены? Чтобы работа с общими ресурсами не приводила к путанице, потокам нужно координировать свои действия. Для этого они обмениваются информацией с помощью сигналов. Каждый поток сообщает другим, что он сейчас делает и каких изменений ждать. Так данные всех потоков о текущем состоянии ресурсов синхронизируются.

В категориях объектно-ориентированного программирования сигналы — это объекты синхронизации. У каждого из них — своя роль во взаимодействии.

Основные средства синхронизации

Взаимоисключение (mutual exclusion, сокращённо — mutex) — «флажок», переходящий к потоку, который в данный момент имеет право работать с общими ресурсами. Исключает доступ остальных потоков к занятому участку памяти. Мьютексов в приложении может быть несколько, и они могут разделяться между процессами. Есть подвох: mutex заставляет приложение каждый раз обращаться к ядру операционной системы, что накладно.

Семафор — позволяет вам ограничить число потоков, имеющих доступ к ресурсу в конкретный момент. Так вы снизите нагрузку на процессор при выполнении кода, где есть узкие места. Проблема в том, что оптимальное число потоков зависит от машины пользователя.

Событие — вы определяете условие, при наступлении которого управление передаётся нужному потоку. Данными о событиях потоки обмениваются, чтобы развивать и логически продолжать действия друг друга. Один получил данные, другой проверил их корректность, третий — сохранил на жёсткий диск. События различаются по способу отмены сигнала о них. Если нужно уведомить о событии несколько потоков, для остановки сигнала придётся вручную ставить функцию отмены. Если же целевой поток только один, можно создать событие с автоматическим сбросом. Оно само остановит сигнал, после того как он дойдёт до потока. Для гибкого управления потоками события можно выстраивать в очередь.

Критическая секция — более сложный механизм, который объединяет в себе счётчик цикла и семафор. Счётчик позволяет отложить запуск семафора на нужное время. Преимущество в том, что ядро задействуется лишь в случае, если секция занята и нужно включать семафор. В остальное время поток выполняется в пользовательском режиме. Увы, секцию можно использовать только внутри одного процесса.

Как реализовать многопоточность в Java

За работу с потоками в Java отвечает класс Thread. Создать новый поток для выполнения задачи — значит создать экземпляр класса Thread и связать его с нужным кодом. Сделать это можно двумя путями:

образовать от Thread подкласс;

имплементировать в своём классе интерфейс Runnable, после чего передавать экземпляры класса в конструктор Thread.

Пока мы не будем затрагивать тему тупиковых ситуаций (deadlock'ов), когда потоки блокируют работу друг друга и зависают — оставим это для следующей статьи. А сейчас перейдём к практике.

Пример многопоточности в Java: пинг-понг мьютексами

Если вы думаете, что сейчас будет что-то страшное — выдохните. Работу с объектами синхронизации мы рассмотрим почти в игровой форме: два потока будут перебрасываться mutex'ом. Но по сути вы увидите реальное приложение, где в один момент времени только один поток может обрабатывать общедоступные данные.

Сначала создадим класс, наследующий свойства уже известного нам Thread, и напишем метод «удара по мячу» (kickBall):

Теперь позаботимся о мячике. Будет он у нас не простой, а памятливый: чтоб мог рассказать, кто по нему ударил, с какой стороны и сколько раз. Для этого используем mutex: он будет собирать информацию о работе каждого из потоков — это позволит изолированным потокам общаться друг с другом. После 15-го удара выведем мяч из игры, чтоб его сильно не травмировать.

А теперь на сцену выходят два потока-игрока. Назовём их, не мудрствуя лукаво, Пинг и Понг:

«Полный стадион народа — время начинать матч». Объявим об открытии встречи официально — в главном классе приложения:

Читайте также: