Mutexes in PHP

In the previous example we saw how to manage simple counter state using atomic operations. For more complex state we can use a mutex to safely access data across multiple threads.

<?php

// Container holds an array of counters; since we want to
// update it concurrently from multiple threads, we
// add a mutex to synchronize access.
// Note that in PHP, we'll use the Swoole extension for multi-threading
// and its Swoole\Mutex class for mutex functionality.
class Container {
    private $mu;
    private $counters;

    public function __construct() {
        $this->mu = new Swoole\Mutex();
        $this->counters = ['a' => 0, 'b' => 0];
    }

    // Lock the mutex before accessing counters; unlock
    // it at the end of the function.
    public function inc($name) {
        $this->mu->lock();
        $this->counters[$name]++;
        $this->mu->unlock();
    }

    public function getCounters() {
        return $this->counters;
    }
}

// This function increments a named counter in a loop.
function doIncrement($container, $name, $n) {
    for ($i = 0; $i < $n; $i++) {
        $container->inc($name);
    }
}

$c = new Container();

// Run several threads concurrently; note
// that they all access the same Container,
// and two of them access the same counter.
$threads = [];
for ($i = 0; $i < 2; $i++) {
    $threads[] = new Swoole\Process(function() use ($c) {
        doIncrement($c, 'a', 10000);
    });
}
$threads[] = new Swoole\Process(function() use ($c) {
    doIncrement($c, 'b', 10000);
});

foreach ($threads as $thread) {
    $thread->start();
}

foreach ($threads as $thread) {
    $thread->wait();
}

print_r($c->getCounters());

Running the program shows that the counters updated as expected.

$ php mutexes.php
Array
(
    [a] => 20000
    [b] => 10000
)

Next we’ll look at implementing this same state management task using only threads and message passing.

Note: This PHP implementation uses the Swoole extension, which provides multi-threading capabilities and mutex functionality. Standard PHP doesn’t support native threading, so Swoole is used as an alternative to demonstrate similar concurrency concepts.

Remember to install and enable the Swoole extension before running this code. The concept of goroutines in Go is approximated using Swoole’s Process class in this PHP version.