Что такое процесс в Elixir?
В Elixir процесс — это изолированная единица выполнения, которая используется для организации параллелизма и конкуренции. Процессы в Elixir являются лёгкими, работают внутри BEAM (виртуальной машины Erlang) и не соответствуют операционным системным процессам или потокам. Это фундаментальная часть модели акторов, на которой построен Elixir.
Особенности процессов Elixir:
-
Изоляция
Каждый процесс полностью изолирован:-
имеет собственное состояние;
-
не делит память с другими;
-
общается только через обмен сообщениями.
-
-
Лёгкость
Один сервер BEAM может запускать сотни тысяч процессов без существенной нагрузки. Это достигается за счёт:-
компактных представлений;
-
кооперативного планирования;
-
отсутствия блокировок и общего состояния.
-
-
Прекрасно масштабируется
Поддерживает горизонтальное масштабирование благодаря лёгкости процессов и их изолированности. BEAM эффективно распределяет нагрузку между ядрами процессора.
Создание процесса
Для создания процесса используется функция spawn/1 или spawn/3.
spawn(fn -> IO.puts "Hello from new process" end)
Это создаёт новый процесс, который выполняет функцию и завершает работу.
Идентификатор процесса (PID)
Каждый процесс имеет уникальный идентификатор — PID. Его можно сохранить, передать или использовать для отправки сообщений:
pid = spawn(fn -> receive do msg -> IO.inspect(msg) end end)
send(pid, "Message") # Отправка сообщения в процесс
Обмен сообщениями
Процессы обмениваются сообщениями с помощью send и receive. Это асинхронная модель:
send(pid, {:greet, "world"})
receive do
{:greet, name} -> IO.puts("Hello, #{name}")
after
1000 -> IO.puts("Timeout")
end
receive — это блокирующий вызов с необязательной секцией after.
Пример: простая эхо-служба
defmodule Echo do
def listen do
receive do
{:echo, msg, sender} ->
send(sender, {:ok, msg})
listen()
end
end
end
pid = spawn(Echo, :listen, \[\])
send(pid, {:echo, "Hello", self()})
receive do
{:ok, response} -> IO.puts(response)
end
Ссылки и мониторинг
Для контроля других процессов:
-
Process.link(pid) — создаёт связь: если один процесс падает, связанный тоже упадёт.
-
Process.monitor(pid) — создаёт односторонний мониторинг, чтобы получать сообщение :DOWN.
Анонимные и именованные процессы
-
Анонимный — просто spawn(fn -> ... end).
-
Именованный — через :register.
:register(:my_worker, pid)
send(:my_worker, :ping)
Планировщик и многозадачность
Процессы выполняются в рамках планировщика BEAM. Планировщик работает по кооперативной многозадачности: каждый процесс получает квант времени (reductions), после чего управление передаётся следующему.
Преимущества такой модели:
-
Нет гонок за данные (race conditions).
-
Нет общей блокировки (lock-free).
-
Ошибки одного процесса не влияют на другие.
-
Возможность построения отказоустойчивых систем.
Применение
Процессы активно используются в:
-
фреймворке GenServer для создания состояний и логики серверов;
-
построении супервизоров (supervisors);
-
реализации распределённых систем;
-
обработке параллельных задач, таймеров, очередей, подписок.
Процессы являются основой актерной модели, в которой Elixir реализует устойчивую, масштабируемую и легко отлаживаемую многопоточную архитектуру.