/
spirzen
/
it-knowledge-base
Обзор
Документация
Войти
/
spirzen
/
it-knowledge-base
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
Mobile
src/components/shared/concurrencyLifecycleEngine.js
274 строки
12 KB
Spirzen
Big design pack
04 июн 2026, 02:45
04 июн 2026, 02:45
50bc995
Код
Авторство
О чём код?
/** Сценарии пошаговых демо: поток, процесс, Promise — статьи 4-05-asinhronnost/2 и 5-01-javascript/21. */ export const THREAD_DEMO = { language: 'Python · threading', codeLines: [ 'import threading', '', 'balance = 1000 # общая память процесса', 'lock = threading.Lock()', '', 'def export_report():', ' global balance', ' with lock:', ' balance -= 50 # критическая секция', '', 'worker = threading.Thread(target=export_report)', 'worker.start() # ОС выделяет поток', 'worker.join() # главный ждёт worker', 'print(balance)', ], steps: [ { id: 'main-only', title: 'Один процесс, один главный поток', highlight: [2, 3], activeThreads: ['main'], memory: {shared: ['balance = 1000'], isolated: []}, osNote: 'Программа уже запущена как процесс. Пока есть только главный поток — он владеет всей памятью процесса.', codeNote: 'Переменная balance лежит в общем адресном пространстве. Потоков пока один.', }, { id: 'thread-object', title: 'Объект Thread — ещё не поток ОС', highlight: [10], activeThreads: ['main'], memory: {shared: ['balance = 1000', 'worker (объект Python)'], isolated: []}, osNote: 'Строка Thread(...) создаёт только описание задачи. ОС пока ничего не выделяла.', codeNote: 'Это как записать "нужен второй официант", но он ещё не вышел в зал.', }, { id: 'start', title: 'start() — ОС создаёт поток', highlight: [11], activeThreads: ['main', 'worker'], memory: { shared: ['balance = 1000', 'lock', 'код export_report'], isolated: ['стек worker (~1 МБ)', 'регистры worker', 'thread id'], }, osNote: 'start() просит ядро: новый поток, свой стек, свой счётчик команд. Память с данными — та же, что у главного потока.', codeNote: 'Главный поток не ждёт — сразу идёт дальше. Worker может уже выполняться параллельно.', }, { id: 'worker-run', title: 'Worker выполняет функцию', highlight: [6, 7, 8], activeThreads: ['worker'], memory: {shared: ['balance → 950 (после lock)'], isolated: ['стек worker']}, osNote: 'Планировщик переключает CPU между потоками. Оба видят одну переменную balance — нужен lock.', codeNote: 'with lock — мьютекс: только один поток в критической секции, второй ждёт.', }, { id: 'join', title: 'join() — главный поток ждёт', highlight: [12], activeThreads: ['main', 'worker'], memory: {shared: ['balance = 950'], isolated: []}, osNote: 'Главный поток блокируется, пока worker не завершится. UI-поток в десктопе здесь же "завис бы", если join без фона.', codeNote: 'join() = "дождись конца worker". Для UI тяжёлую работу делают в worker, а join — аккуратно, с прогрессом.', }, { id: 'done', title: 'Worker завершён, ресурсы освобождены', highlight: [13], activeThreads: ['main'], memory: {shared: ['balance = 950'], isolated: []}, osNote: 'Поток worker уничтожен. Остался один главный поток и общая память с результатом.', codeNote: 'Итог: два потока делили одну память, синхронизировались через lock. Процесс один.', }, ], }; export const PROCESS_DEMO = { language: 'Python · multiprocessing', codeLines: [ 'from multiprocessing import Process, Queue', '', 'def worker(out_queue):', ' result = {"status": "ok", "rows": 100_000}', ' out_queue.put(result) # IPC, не общая переменная', '', 'if __name__ == "__main__":', ' queue = Queue()', ' child = Process(target=worker, args=(queue,))', ' child.start() # новый процесс ОС', ' data = queue.get() # ждём сообщение', ' child.join()', ' print(data["rows"])', ], steps: [ { id: 'parent', title: 'Родительский процесс', highlight: [7], processes: [{id: 'parent', role: 'Родитель', memory: ['queue', 'переменные main'], active: true}], ipc: [], osNote: 'Один процесс = своё адресное пространство. Переменные родителя недоступны дочернему напрямую.', codeNote: 'Queue() — канал обмена через ОС, не "общая RAM".', }, { id: 'process-object', title: 'Process(...) — заготовка, не процесс', highlight: [8], processes: [{id: 'parent', role: 'Родитель', memory: ['queue', 'child (объект)'], active: true}], ipc: [], osNote: 'Как с Thread: объект в Python ≠ процесс в ОС.', codeNote: 'Указали, какую функцию запустить и куда передать queue.', }, { id: 'start', title: 'start() — ОС создаёт дочерний процесс', highlight: [9], processes: [ {id: 'parent', role: 'Родитель', memory: ['queue', 'свой balance недоступен child'], active: true}, {id: 'child', role: 'Дочерний', memory: ['своя копия Python', 'args: queue'], active: true}, ], ipc: ['Queue (pipe)'], osNote: 'fork/spawn: новый PID, изолированная память. Ошибка в child не портит память parent — как вкладка Chrome.', codeNote: 'child.start() — родитель не ждёт, идёт к queue.get().', }, { id: 'child-work', title: 'Child считает и кладёт результат в очередь', highlight: [2, 3, 4], processes: [ {id: 'parent', role: 'Родитель', memory: ['ждёт queue.get()'], active: false}, {id: 'child', role: 'Дочерний', memory: ['result локально'], active: true}, ], ipc: ['put({"status":"ok",...}) → Queue'], osNote: 'Данные копируются в очередь — это IPC. Нет гонки за общую переменную между процессами.', codeNote: 'worker не видит переменные родителя — только то, что передали в args.', }, { id: 'receive', title: 'Родитель получает сообщение', highlight: [10], processes: [ {id: 'parent', role: 'Родитель', memory: ['data = {...}'], active: true}, {id: 'child', role: 'Дочерний', memory: ['завершается'], active: false}, ], ipc: ['get() ← Queue'], osNote: 'Блокирующее чтение из очереди — родитель просыпается, когда child положил результат.', codeNote: 'Обмен завершён без общей памяти.', }, { id: 'join', title: 'join() и выход child', highlight: [11, 12], processes: [{id: 'parent', role: 'Родитель', memory: ['data', 'print 100000'], active: true}], ipc: [], osNote: 'Дочерний процесс уничтожен. Родитель продолжает один.', codeNote: 'Итог: изоляция + обмен через Queue. Дороже потока, но безопаснее.', }, ], }; export const PROMISE_DEMO = { language: 'JavaScript · Promise + fetch', codeLines: [ "console.log('A: шапка отрисована');", '', 'showSpinner();', '', "fetch('/api/posts')", ' .then(res => res.json())', ' .then(posts => {', ' hideSpinner();', " render(posts);", ' });', '', "console.log('B: UI не заблокирован');", ], steps: [ { id: 'sync-a', title: 'Синхронный код в Call Stack', highlight: [0], stack: ['main()'], webApi: null, micro: [], macro: [], console: ['A: шапка отрисована'], osNote: 'Один поток JS. Стек выполняет строки сверху вниз.', codeNote: 'console.log отработал сразу — пользователь видит шапку.', }, { id: 'spinner', title: 'showSpinner() — всё ещё синхронно', highlight: [2], stack: ['main()', 'showSpinner()'], webApi: null, micro: [], macro: [], console: ['A: шапка отрисована'], osNote: 'DOM обновился синхронно — спиннер на экране.', codeNote: 'До fetch интерфейс уже отзывчивый элементами UI.', }, { id: 'fetch-delegate', title: 'fetch уходит в Web API — стек не ждёт', highlight: [4], stack: ['main()'], webApi: 'fetch /api/posts (сеть ~800 ms)', micro: [], macro: [], console: ['A: шапка отрисована'], osNote: 'Браузер/Node сам ждёт сеть. JS-поток освобождён — не блокируем UI.', codeNote: 'fetch возвращает Promise в состоянии pending.', }, { id: 'sync-b', title: 'Следующая строка выполняется сразу', highlight: [11], stack: ['main()'], webApi: 'fetch /api/posts (сеть ~800 ms)', micro: [], macro: [], console: ['A: шапка отрисована', 'B: UI не заблокирован'], osNote: 'Пока сеть думает — event loop обрабатывает клики, анимацию, другой код.', codeNote: 'Ключ async: B выводится ДО ответа сервера.', }, { id: 'network-done', title: 'Ответ пришёл — then попадает в microtask', highlight: [5], stack: ['main()'], webApi: null, micro: ['.then(res => res.json())'], macro: [], console: ['A: шапка отрисована', 'B: UI не заблокирован'], osNote: 'Promise fulfilled → колбэк в очередь микрозадач (выше приоритет, чем setTimeout).', codeNote: 'Event loop сначала опустошит microtasks.', }, { id: 'micro-1', title: 'Первый .then — json()', highlight: [5], stack: ['(microtask) res.json()'], webApi: 'parse JSON', micro: ['.then(posts => render)'], macro: [], console: ['A: шапка отрисована', 'B: UI не заблокирован'], osNote: 'Цепочка Promise — каждый then порождает следующий microtask.', codeNote: 'res.json() тоже async — вернёт новый Promise.', }, { id: 'micro-2', title: 'Второй .then — render', highlight: [6, 7, 8], stack: ['(microtask) render(posts)'], webApi: null, micro: [], macro: [], console: ['A: шапка отрисована', 'B: UI не заблокирован', '→ лента на экране'], osNote: 'Спиннер скрыт, DOM обновлён. Потоков OS не добавляли — один event loop.', codeNote: 'Итог: async I/O без блокировки главного потока JS.', }, ], }; export function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); }