Mutexes in Perl
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.
use strict;
use warnings;
use threads;
use Thread::Semaphore;
use Data::Dumper;
# Container holds a hash of counters; since we want to
# update it concurrently from multiple threads, we
# add a semaphore to synchronize access.
package Container {
sub new {
my $class = shift;
my $self = {
semaphore => Thread::Semaphore->new(),
counters => { a => 0, b => 0 },
};
return bless $self, $class;
}
# Lock the semaphore before accessing counters; unlock
# it at the end of the function.
sub inc {
my ($self, $name) = @_;
$self->{semaphore}->down();
$self->{counters}->{$name}++;
$self->{semaphore}->up();
}
}
# This function increments a named counter
# in a loop.
sub do_increment {
my ($container, $name, $n) = @_;
for (1..$n) {
$container->inc($name);
}
}
my $c = Container->new();
# Run several threads concurrently; note
# that they all access the same Container,
# and two of them access the same counter.
my @threads = (
threads->create(\&do_increment, $c, 'a', 10000),
threads->create(\&do_increment, $c, 'a', 10000),
threads->create(\&do_increment, $c, 'b', 10000),
);
# Wait for the threads to finish
$_->join for @threads;
print Dumper($c->{counters});Running the program shows that the counters updated as expected.
$ perl mutexes.pl
$VAR1 = {
'a' => 20000,
'b' => 10000
};Next we’ll look at implementing this same state management task using only threads and queues.
In this Perl implementation:
We use the
threadsmodule for creating and managing threads, which is similar to goroutines in Go.Instead of a mutex, we use a
Thread::Semaphorefor synchronization. This serves the same purpose as the mutex in the Go example.The
Containeris implemented as a Perl package with methods for initialization and incrementing counters.The
incmethod uses the semaphore’sdownandupmethods to lock and unlock access to the shared data, similar toLockandUnlockin Go.We create threads using
threads->createand join them using thejoinmethod, which is analogous to using goroutines andWaitGroupin Go.Finally, we use
Data::Dumperto print the contents of the counters hash, which gives a similar output to the Go version.
This Perl code demonstrates the same concepts of safe concurrent access to shared data as the original Go example, adapted to Perl’s threading and synchronization mechanisms.