module. In our example above, that's what MyMod_threaded is, and it's
only imported if we're running on a threaded Perl.
+=head2 A Note about the Examples
+
+Although thread support is considered to be stable, there are still a number
+of quirks that may startle you when you try out any of the examples below.
+In a real situation, care should be taken that all threads are finished
+executing before the program exits. That care has B<not> been taken in these
+examples in the interest of simplicity. Running these examples "as is" will
+produce error messages, usually caused by the fact that there are still
+threads running when the program exits. You should not be alarmed by this.
+Future versions of Perl may fix this problem.
+
=head2 Creating Threads
The L<threads> package provides the tools you need to create new
$Param3 = "foo";
$thr = threads->new(\&sub1, "Param 1", "Param 2", $Param3);
$thr = threads->new(\&sub1, @ParamList);
- $thr = threads->new(\&sub1, qw(Param1 Param2 $Param3));
+ $thr = threads->new(\&sub1, qw(Param1 Param2 Param3));
sub sub1 {
my @InboundParameters = @_;
this. yield() is pretty straightforward, and works like this:
use threads;
-
+
sub loop {
my $thread = shift;
my $foo = 50;
while($foo--) { print "in thread $thread\n" }
- threads->yield();
+ threads->yield;
$foo = 50;
while($foo--) { print "in thread $thread\n" }
}
my $thread1 = threads->new(\&loop, 'first');
my $thread2 = threads->new(\&loop, 'second');
my $thread3 = threads->new(\&loop, 'third');
-
+
It is important to remember that yield() is only a hint to give up the CPU,
it depends on your hardware, OS and threading libraries what actually happens.
Therefore it is important to note that one should not build the scheduling of
my $foo : shared = 1;
my $bar = 1;
threads->new(sub { $foo++; $bar++ })->join;
-
+
print "$foo\n"; #prints 2 since $foo is shared
print "$bar\n"; #prints 1 since $bar is not shared
my $c : shared;
my $thr1 = threads->create(sub { $b = $a; $a = $b + 1; });
my $thr2 = threads->create(sub { $c = $a; $a = $c + 1; });
- $thr1->join();
- $thr2->join();
+ $thr1->join;
+ $thr2->join;
Two threads both access $a. Each thread can potentially be interrupted
at any point, or be executed in any order. At the end, $a could be 3
The lock() function takes a shared variable and puts a lock on it.
No other thread may lock the variable until the the variable is unlocked
by the thread holding the lock. Unlocking happens automatically
-when the locking thread exists the outermost block that contains
+when the locking thread exits the outermost block that contains
C<lock()> function. Using lock() is straightforward: this example has
several threads doing some calculations in parallel, and occasionally
updating a running total:
# (... do some calculations and set $result ...)
{
lock($total); # block until we obtain the lock
- $total += $result
+ $total += $result;
} # lock implicitly released at end of scope
last if $result == 0;
}
{
{
lock($x); # wait for lock
- lock($x): # NOOP - we already have the lock
+ lock($x); # NOOP - we already have the lock
{
lock($x); # NOOP
{
use threads;
use threads::shared::queue;
- my $DataQueue = threads::shared::queue->new();
+ my $DataQueue = threads::shared::queue->new;
$thr = threads->new(sub {
while ($DataElement = $DataQueue->dequeue) {
print "Popped $DataElement off the queue\n";
$DataQueue->enqueue(\$thr);
sleep 10;
$DataQueue->enqueue(undef);
- $thr->join();
+ $thr->join;
You create the queue with C<new threads::shared::queue>. Then you can
add lists of scalars onto the end with enqueue(), and pop scalars off
}
}
- $thr1->join();
- $thr2->join();
- $thr3->join();
+ $thr1->join;
+ $thr2->join;
+ $thr3->join;
The three invocations of the subroutine all operate in sync. The
semaphore, though, makes sure that only one thread is accessing the
$semaphore->up(5); # Increment the counter by five
}
- $thr1->detach();
- $thr2->detach();
+ $thr1->detach;
+ $thr2->detach;
If down() attempts to decrement the counter below zero, it blocks until
the counter is large enough. Note that while a semaphore can be created
14 }
15
16 $stream->enqueue(undef);
- 17 $kid->join();
+ 17 $kid->join;
18
19 sub check_num {
20 my ($upstream, $cur_prime) = @_;
30 }
31 }
32 $downstream->enqueue(undef) if $kid;
- 33 $kid->join() if $kid;
+ 33 $kid->join if $kid;
34 }
This program uses the pipeline model to generate prime numbers. Each
=head1 Threadsafety of System Libraries
Whether various library calls are threadsafe is outside the control
-of Perl. Calls often suffering from not being threadsafe include
+of Perl. Calls often suffering from not being threadsafe include:
localtime(), gmtime(), get{gr,host,net,proto,serv,pw}*(), readdir(),
-rand(), srand(). If the system Perl is compiled in has threadsafe
-variants of these calls, they will be used, but besides that, Perl is
-at the mercy of the thread safety or unsafety of the calls. Please
-consult your C library call documentation.
+rand(), and srand() -- in general, calls that depend on some external
+state.
+
+If the system Perl is compiled in has threadsafe variants of such
+calls, they will be used. Beyond that, Perl is at the mercy of
+the threadsafety or unsafety of the calls. Please consult your
+C library call documentation.
+
+In some platforms the threadsafe interfaces may fail if the result
+buffer is too small (for example getgrent() may return quite large
+group member lists). Perl will retry growing the result buffer
+a few times, but only up to 64k (for safety reasons).
=head1 Conclusion