Як можна досягти багатопотокової функціональності на мові високого рівня, наприклад, на Java, використовуючи лише одну нитку та стан машини? Наприклад, що робити для виконання 2-х дій (робити обчислення та робити введення-виведення), і одна діяльність може блокуватись?
Те, що ви описуєте, називається кооперативним багатозадачністю , де завданням дається ЦП та, як очікується, відмовляться від нього добровільно після певного часу або активності, що визначається самостійно. Завдання, яке не співпрацює, продовжуючи використовувати центральний процесор або блокуючи камеді протягом усіх робіт і не маючи апаратного таймера сторожового собаки, коду, що контролює завдання, не може виконувати з цим.
Те, що ви бачите в сучасних системах, називається попереджувальним багатозадачністю , саме там завданням не потрібно відмовлятися від центрального процесора, оскільки керівник робить це за них, коли надходить апаратне переривання. Процедура служби переривання в супервізорі зберігає стан центрального процесора та відновлює його наступного разу, коли завдання вважається заслуговуючим на часовий відрізок, а потім відновлює стан з будь-якої задачі, яку слід виконати поруч, і стрибає назад у неї, як ніби нічого не сталося . Ця дія називається контекстним перемиканням і може бути дорогою.
Чи використовується "лише державна машина" способом життєздатна альтернатива багатопотоковій мові високого рівня?
Життєздатний? Звичайно. Здоровий? Іноді. Незалежно від того, чи використовуєте ви нитки або якусь форму домашньої кооперативної багатозадачності (наприклад, державні машини), залежить від компромісів, які ви готові зробити.
Нитки спрощують розробку завдань до того моменту, коли ви можете ставитися до кожного як до власної програми, яка має спільний доступ до даних з іншими. Це дає вам свободу зосередитись на роботі, а не всьому управлінському та господарському господарству, необхідному для того, щоб він працював ітерацією за раз. Але оскільки жодна добра справа не залишається безкарною, ви сплачуєте за все це зручність в контекстних комутаторах. Маючи багато потоків, які дають процесор після мінімальної роботи (добровільно або виконуючи щось, що блокує, як-от введення-виведення), може з'їсти багато процесорного часу, роблячи переключення контексту. Це особливо актуально, якщо операції з блокування рідко блокуються дуже довго.
Є деякі ситуації, коли шлях спільної роботи має більше сенсу. Мені колись довелося написати програмне забезпечення для користувальницької частини обладнання, яке передало багато каналів даних через інтерфейс, нанесений на пам'ять, який вимагав опитування. Кожен канал був об'єктом, побудованим таким чином, що я міг або дозволити йому працювати як потік, або повторно виконувати один цикл опитування.
Продуктивність багатопотокової версії зовсім не була хорошою саме з тієї причини, яку я окреслив вище: кожен потік робив мінімальну роботу, а потім давав процесор, щоб інші канали могли мати деякий час, викликаючи безліч контекстних комутацій. Відпущення потоків до тих пір, поки попередньо не допоможе пропускна спроможність, але в результаті деякі канали не отримали обслуговування до того, як апаратне забезпечення зазнало перевищення буфера, оскільки вони не отримали досить швидкий відрізок часу.
Однопоточна версія, яка робила навіть ітерації кожного каналу, проходила, як ошпарена мавпа, і навантаження на систему падало, як скеля. Штраф, який я заплатив за додатковий виступ, мав сам перемикати завдання. У цьому випадку код зробити це було досить просто, щоб витрати на його розробку та підтримку були варті того, щоб покращити продуктивність. Я думаю, це справді суть. Якби мої теми були, які сиділи навколо, чекаючи, коли якийсь системний дзвінок повернеться, вправа, мабуть, не вартувала б цього.
Це підштовхує мене до коментаря Кокса: теми не призначені виключно для людей, які не вміють писати державні машини. Деякі люди цілком здатні це робити, але вирішують скористатися консервованою машиною (тобто ниткою) в інтересах зробити роботу раніше чи з меншою складністю.