Эмуляция многопоточности: прототип виртуальной машины (JAVA)
О ПРОЕКТЕ Это не совсем документация и не совсем README. Это скорее небольшое описание проекта, который я написал, чтобы самому лучше разобраться в процессах, потоках и всём том фундаменте, который обычно где-то есть “под капотом”.
Более полное описание, код и примеры находятся в репозитории на GitHub: https://github.com/d1nkache/os-process-emulator
ДЛЯ ЧЕГО Это прототип учебной виртуальной машины, написанной на Java. Цель данного проекта -разобраться в том, что такое процессы и что они из себя представляют на самом деле. Это фундаментальные знания, которые необходимы для точного осознания того, что такое многопоточность, как делать код потокобезопасным, для чего потоки синхронизируют и какими методами. В общем и целом, это необходимо для того, чтобы разобраться в том, что такое асинхронность и почему это круто.
В предыдущем абзаце я употребил словосочетание “для точного осознания” - и это не просто так. Дело в том, что между осознанием и знанием, как по мне, есть принципиальные отличия. Знать человек может всё что угодно: что такое инкапсуляция, что такое эндпоинт, что такое виджет во фреймворке и как в нём добавить тень. Однако осознавать человек может не всё что угодно. Осознавать - значит понимать принцип работы. Осознавать - значит понимать фундамент, хотя бы чуть-чуть. Осознавать - значит понимать, почему это используется именно тут, а не где-то ещё.
Именно ради этого я и писал данный проект. Не чтобы сделать “свою ОС”, а чтобы руками потрогать маленькую модель того, как вообще могут жить процессы, потоки, память, планировщик и интерпретатор.
ЧТО ВНУТРИ В проекте есть несколько основных компонентов:
VirtualMachine - это кокон всей системы, высшая инстанция, которая связывает воедино память, планировщик и интерпретатор. Если Heap - это тело, а Scheduler - сердце, то VirtualMachine - это сам организм.
Scheduler представляет из себя очень упрощённую модель планировщика. Тем не менее с главной задачей - распределением процессорного времени между потоками разных процессов - он справляется на ура. Ключевым полем данного класса является runQueue, то очередь потоков, которые готовы к исполнению.
TaskStruct - это сущность, через которую в проекте представлены и процессы, и потоки. Модель вдохновлена Linux: всё есть TaskStruct. Каждый экземпляр фактически представляет из себя отдельный поток, а по threadGroupId можно понять, какие потоки относятся к одному процессу.
Heap, Segment, SegmentBuilder и SegmentReader отвечают за модель памяти. Heap представляет из себя имитацию адресного пространства процесса, а данные внутри сегментов хранятся в виде битов.
Interpreter - это мозг системы. Именно он вдыхает жизнь в статичные строки кода, превращая их в реальные манипуляции над регистрами, памятью и потоками. Язык, который воспринимает интерпретатор, имеет расширение .dinka.
ВАЖНЫЙ МОМЕНТ Данная реализация не является потокобезопасной. И фактически возможность создавать потоки добавлена исключительно ради многопоточности, но при этом без полноценной асинхронности. Возможно, в будущем доработаю и добавлю потокобезопасность - это было бы следующим крепким шагом на пути к осознанию.
ИТОГИ Здесь я специально описал проект кратко, без сильного углубления в теорию. Если хочется посмотреть код, структуру, примеры .dinka-программ и более подробное описание того, как всё работает внутри, то это всё есть в репозитории:
https://github.com/d1nkache/os-process-emulator
Очень жаль, что эти знания мало кем ценятся. Особенно в эпоху нейросетей. Нейросети - это очень мощный инструмент, позволяющий крайне быстро учиться чему-то новому, причём уровень обучения выходит на радикально иной, более качественный уровень. Но, как по мне, важно не позволить им заменить сам процесс понимания. Они могут подсказать, ускорить, направить, объяснить, но осознание всё равно должно оставаться за человеком.
Не позволяйте нейросетям поставить вас на ступень эволюции ниже, чем они.