jonnifyelixir
F3 · The Elixir Language / F3.07 · processes

F3 · The actor model · module 7

Concurrency: processes & the actor model

A process is the BEAM's unit of concurrency — a lightweight, isolated worker with its own heap and its own mailbox, scheduled across every core. Processes share no memory. They coordinate only by sending messages. That is the actor model, and it is how Elixir does concurrency, state, and fault isolation all at once.

The portal runs work in processes: a session server here, a notifier there. This module builds the actor from three primitives — spawn a process, send and receive messages, then loop to hold state. F3.08 wraps the whole pattern in a GenServer.

Why a crash stays put

TWO PROCESSES · SHARED NOTHING #PID<0.118.0> PRIVATE HEAP {count: 7} alive #PID<0.119.0> PRIVATE HEAP {count: 7} alive :ping FAULT BOUNDARY no shared state to corrupt

[ 0.118.0 alive · 0.119.0 alive ]
Two heaps, no shared memory; one message channel between them.

The actor in three moves

An actor is not a class or a thread you reach into. It is a process you start, send messages to, and that keeps itself alive by looping. Select each move to see which part of the actor it drives.

The move · select one

MAILBOX {:summarize, …} :inc {:get, from} PROCESS (actor) #PID<0.118.0> receive · handle loop PROPERTIES isolated · own heap · scheduled on any core

Concurrency, state, and isolation are not three features here — they are one idea. A process runs on its own, remembers by looping, and a crash stays inside its boundary.

Three deep dives

Three pages, in order: starting a process and what isolation buys you; the mailbox and selective receive; then the recursive loop that turns a process into a stateful server.

F3.07.1
Spawning a process
spawn/1 starts a function as a new process and returns its PID at once; the child runs concurrently, with its own heap and crash boundary.
F3.07.2
Sending & receiving messages
send/2 drops a term in a mailbox; receive matches it out. A message can carry a PID, so the receiver can reply.
F3.07.3
Holding state in a loop
State is the argument to a recursive receive loop; the process tail-calls itself with updated state — the pattern GenServer abstracts.

F3.06 · a module's contract

A behaviour fixed the functions a module must implement — a static shape, checked at compile time.

F3.07 · a running process

Spawn that module and it comes alive: a concurrent actor that holds state in a loop and a crash boundary of its own.

Start with spawning a process, then sending and receiving messages, then holding state in a loop. Next module: F3.08 — OTP: GenServer & supervisors, where this pattern becomes a behaviour with supervision.

References

Primary sources for this lesson, and where it connects in the course.

Sources

Related in this course