Как достичь многопоточной функциональности на языке высокого уровня, таком как Java, используя только один поток и конечный автомат? Например, что делать, если нужно выполнить 2 действия (выполнение вычислений и ввод / вывод) и одно действие можно заблокировать?
То, что вы описываете, называется кооперативной многозадачностью , где задачи передаются ЦПУ и ожидаются добровольно, по истечении некоторого времени или активности. Задача, которая не взаимодействует, продолжая использовать ЦП или блокируя гуммирование всей работы и не имея аппаратного сторожевого таймера, код, контролирующий задачи, ничего не может с этим поделать.
То, что вы видите в современных системах, называется упреждающей многозадачностью , когда задачам не нужно освобождать ЦП, потому что супервизор делает это за них, когда прибывает аппаратное прерывание. Процедура обработки прерываний в супервизоре сохраняет состояние ЦП и восстанавливает его в следующий раз, когда задача считается заслуживающей временного интервала, затем восстанавливает состояние из любой задачи, которая должна быть запущена следующей, и возвращается к ней, как будто ничего не произошло , Это действие называется переключением контекста и может быть дорогим.
Является ли использование только конечного автомата жизнеспособной альтернативой многопоточности в языках высокого уровня?
Жизнеспособное? Конечно. Здравомыслящий? Иногда. Используете ли вы потоки или некоторую форму домашней многозадачной кооперации (например, конечные автоматы), зависит от компромиссов, которые вы готовы сделать.
Потоки упрощают проектирование задач до такой степени, что вы можете рассматривать каждую из них как свою собственную программу, которая может совместно использовать пространство данных с другими. Это дает вам свободу сосредоточиться на текущей работе, а не на всех управленческих и хозяйственных работах, необходимых для того, чтобы заставить ее работать итерацию за раз. Но поскольку ни одно доброе дело не остается безнаказанным, вы платите за все это удобство в переключениях контекста. Наличие множества потоков, которые выдают ЦП после выполнения минимальной работы (добровольно или делая что-то, что блокирует, например, ввод / вывод), может потреблять много процессорного времени при переключении контекста. Это особенно верно, если ваши блокирующие операции редко блокируются очень долго.
В некоторых ситуациях маршрут сотрудничества имеет больше смысла. Однажды мне пришлось написать какое-то пользовательское программное обеспечение для аппаратного обеспечения, которое передавало много каналов данных через отображаемый в памяти интерфейс, который требовал опроса. Каждый канал был объектом, построенным таким образом, что я мог либо позволить ему работать как поток, либо повторно выполнить один цикл опроса.
Производительность многопоточной версии совсем не была хороша именно по той причине, о которой я говорил выше: каждый поток выполнял минимальную работу, а затем выдавал процессор, чтобы другие каналы могли иметь некоторое время, вызывая много переключений контекста. Позволение потокам работать свободно до тех пор, пока выгрузка не будет прервана, что помогло с пропускной способностью, но привело к тому, что некоторые каналы не обслуживались до того, как аппаратное обеспечение испытало переполнение буфера, потому что они не получили достаточный интервал времени.
Однопоточная версия, которая выполняла даже итерации каждого канала, работала как обезжиренная обезьяна, а нагрузка на систему падала как скала. Штраф, который я заплатил за дополнительное выступление, заключался в том, что я сам подтасовывал задачи. В этом случае код для его выполнения был достаточно прост, чтобы затраты на его разработку и поддержку стоили повышения производительности. Я думаю, что это действительно суть. Если бы мои потоки сидели без дела, ожидая возвращения какого-то системного вызова, упражнение, вероятно, не стоило бы того.
Это приводит меня к комментарию Кокса: темы предназначены не только для людей, которые не могут писать конечные автоматы. Некоторые люди вполне способны на это, но предпочитают использовать постоянный конечный автомат (т. Е. Поток) в интересах выполнения работы раньше или с меньшей сложностью.