Что такое процесс в Elixir?

В Elixir процесс — это изолированная единица выполнения, которая используется для организации параллелизма и конкуренции. Процессы в Elixir являются лёгкими, работают внутри BEAM (виртуальной машины Erlang) и не соответствуют операционным системным процессам или потокам. Это фундаментальная часть модели акторов, на которой построен Elixir.

Особенности процессов Elixir:

  1. Изоляция
    Каждый процесс полностью изолирован:

    • имеет собственное состояние;

    • не делит память с другими;

    • общается только через обмен сообщениями.

  2. Лёгкость
    Один сервер BEAM может запускать сотни тысяч процессов без существенной нагрузки. Это достигается за счёт:

    • компактных представлений;

    • кооперативного планирования;

    • отсутствия блокировок и общего состояния.

  3. Прекрасно масштабируется
    Поддерживает горизонтальное масштабирование благодаря лёгкости процессов и их изолированности. 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 реализует устойчивую, масштабируемую и легко отлаживаемую многопоточную архитектуру.