PHP 8.1 Fibers: Writing Cooperative Concurrency Without a Framework
What Fibers Actually Are
A Fiber is a stackful coroutine — a function that can suspend its own execution and yield control back to the caller, then be resumed from exactly where it stopped. No OS threads. No shared memory. Full control of the scheduler.
$fiber = new Fiber(function(): string {
$value = Fiber::suspend('first suspension');
echo "Resumed with: {$value}\n";
return 'fiber complete';
});
$firstValue = $fiber->start(); // returns 'first suspension'
$returnValue = $fiber->resume('hello'); // prints "Resumed with: hello"
// $returnValue === 'fiber complete'
The key insight: Fiber::suspend() is called from inside the fiber, not outside it. The caller gets back whatever was passed to suspend() and can send data back via resume().
Building a Simple Cooperative Scheduler
The real power emerges when you run multiple fibers through a scheduler loop:
class Scheduler
{
private array $fibers = [];
public function add(Fiber $fiber): void
{
$this->fibers[] = $fiber;
}
public function run(): void
{
while ($this->fibers) {
foreach ($this->fibers as $key => $fiber) {
if (!$fiber->isStarted()) $fiber->start();
elseif ($fiber->isSuspended()) $fiber->resume();
if ($fiber->isTerminated()) {
unset($this->fibers[$key]);
}
}
}
}
}
Each iteration of the outer loop ticks all registered fibers once. When a fiber suspends, the scheduler moves on to the next one. This is cooperative multitasking — no OS involvement, fully deterministic.
Practical Use Case: Non-Blocking I/O Simulation
function fetchUrl(string $url): Generator
{
// In a real event loop, this would be non-blocking socket I/O.
// Here we simulate it with a suspend point.
Fiber::suspend('waiting');
return file_get_contents($url);
}
$scheduler = new Scheduler();
foreach ($urls as $url) {
$scheduler->add(new Fiber(function() use ($url) {
$result = yield from fetchUrl($url);
echo "Got " . strlen($result) . " bytes from {$url}\n";
}));
}
$scheduler->run();
The Relationship to ReactPHP and AMPHP
Fibers are the foundation that modern PHP async frameworks build on. Before PHP 8.1, ReactPHP used generators and a complex callback chain. Now both ReactPHP and AMPHP use Fibers as their suspension primitive, giving you async I/O with code that looks sequential.
Understanding Fibers at this level makes frameworks like AMPHP far less magical — you can debug their scheduler, reason about execution order, and write extensions without cargo-culting patterns.
What Fibers Are Not
- They are not threads — no parallelism, no shared-memory races
- They are not true async — they need an event loop to be useful for I/O
- They are not a replacement for queues — CPU-bound work still blocks the process
Use Fibers for I/O multiplexing and cooperative scheduling. Use queues (Laravel Horizon, Beanstalkd) for CPU-bound background work.