X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pod%2Fperlthrtut.pod;h=55a4cd56f96de7a4626fadd1f62ceb1d8ea1e1ae;hb=18fd877aa5c85a3f8bdc7cb30b117cf8f0fe97a6;hp=a3e33129078dc2b4ba8df6496a6c74212afc82cb;hpb=2ad6cdcfe92dde0478294e91d9e270fa0160af98;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pod/perlthrtut.pod b/pod/perlthrtut.pod index a3e3312..55a4cd5 100644 --- a/pod/perlthrtut.pod +++ b/pod/perlthrtut.pod @@ -10,9 +10,9 @@ model, each thread runs in its own Perl interpreter, and any data sharing between threads must be explicit. The user-level interface for I uses the L class. -B: There is another older Perl threading flavor called the 5.005 model -that used the L class. This old model is known to have problems, is -deprecated, and support for it will be removed in release 5.10. You are +B: There was another older Perl threading flavor called the 5.005 model +that used the L class. This old model was known to have problems, is +deprecated, and was removed for release 5.10. You are strongly encouraged to migrate any existing 5.005 threads code to the new model as soon as possible. @@ -117,7 +117,7 @@ step back a bit and think about what you want to do and how Perl can do it. However, it is important to remember that Perl threads cannot magically -do things unless your operating systems threads allows it. So if your +do things unless your operating system's threads allow it. So if your system blocks the entire process on C, Perl usually will, as well. B @@ -323,6 +323,36 @@ detach itself: # Do more work } +=head2 Process and Thread Termination + +With threads one must be careful to make sure they all have a chance to +run to completion, assuming that is what you want. + +An action that terminates a process will terminate I running +threads. die() and exit() have this property, +and perl does an exit when the main thread exits, +perhaps implicitly by falling off the end of your code, +even if that's not what you want. + +As an example of this case, this code prints the message +"Perl exited with active threads: 2 running and unjoined": + + use threads; + my $thr1 = threads->new(\&thrsub, "test1"); + my $thr2 = threads->new(\&thrsub, "test2"); + sub thrsub { + my ($message) = @_; + sleep 1; + print "thread $message\n"; + } + +But when the following lines are added at the end: + + $thr1->join(); + $thr2->join(); + +it prints two lines of output, a perhaps more useful outcome. + =head1 Threads And Data Now that we've covered the basics of threads, it's time for our next @@ -394,8 +424,8 @@ number of pitfalls. One pitfall is the race condition: my $thr1 = threads->create(\&sub1); my $thr2 = threads->create(\&sub2); - $thr1->join; - $thr2->join; + $thr1->join(); + $thr2->join(); print("$a\n"); sub sub1 { my $foo = $a; $a = $foo + 1; } @@ -419,8 +449,8 @@ possibility of error: 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 C<$a>. Each thread can potentially be interrupted at any point, or be executed in any order. At the end, C<$a> could be 3 @@ -596,7 +626,6 @@ this: $DataQueue->enqueue(12); $DataQueue->enqueue("A", "B", "C"); - $DataQueue->enqueue(\$thr); sleep(10); $DataQueue->enqueue(undef); $thr->join(); @@ -621,7 +650,7 @@ threads to have the I at any one time. =head2 Basic semaphores Semaphores have two methods, C and C: C decrements the resource -count, while up increments it. Calls to C will block if the +count, while C increments it. Calls to C will block if the semaphore's current count would decrement below zero. This program gives a quick demonstration: @@ -690,12 +719,12 @@ of these defaults simply by passing in different values: If C attempts to decrement the counter below zero, it blocks until the counter is large enough. Note that while a semaphore can be created with a starting count of zero, any C or C always changes the -counter by at least one, and so C<$semaphore->down(0)> is the same as -C<$semaphore->down(1)>. +counter by at least one, and so C<< $semaphore->down(0) >> is the same as +C<< $semaphore->down(1) >>. The question, of course, is why would you do something like this? Why create a semaphore with a starting count that's not one, or why -decrement/increment it by more than one? The answer is resource +decrement or increment it by more than one? The answer is resource availability. Many resources that you want to manage access for can be safely used by more than one thread at once. @@ -718,9 +747,10 @@ threads quietly block and unblock themselves. Larger increments or decrements are handy in those cases where a thread needs to check out or return a number of resources at once. -=head2 cond_wait() and cond_signal() +=head2 Waiting for a Condition -These two functions can be used in conjunction with locks to notify +The functions C and C +can be used in conjunction with locks to notify co-operating threads that a resource has become available. They are very similar in use to the functions found in C. However for most purposes, queues are simpler to use and more intuitive. See @@ -778,7 +808,7 @@ C is a thread object method that returns the thread ID of the thread the object represents. Thread IDs are integers, with the main thread in a program being 0. Currently Perl assigns a unique TID to every thread ever created in your program, assigning the first thread -to be created a tid of 1, and increasing the tid by 1 for each new +to be created a TID of 1, and increasing the TID by 1 for each new thread that's created. When used as a class method, Ctid()> can be used by a thread to get its own TID. @@ -823,33 +853,31 @@ things we've covered. This program finds prime numbers using threads. 7 use threads; 8 use Thread::Queue; 9 - 10 my $stream = Thread::Queue->new(); - 11 for my $i ( 3 .. 1000 ) { - 12 $stream->enqueue($i); - 13 } - 14 $stream->enqueue(undef); - 15 - 16 threads->create(\&check_num, $stream, 2); - 17 $kid->join(); - 18 - 19 sub check_num { - 20 my ($upstream, $cur_prime) = @_; - 21 my $kid; - 22 my $downstream = Thread::Queue->new(); - 23 while (my $num = $upstream->dequeue()) { - 24 next unless ($num % $cur_prime); - 25 if ($kid) { - 26 $downstream->enqueue($num); - 27 } else { - 28 print("Found prime $num\n"); - 29 $kid = threads->create(\&check_num, $downstream, $num); - 30 } - 31 } - 32 if ($kid) { - 33 $downstream->enqueue(undef); - 34 $kid->join(); - 35 } - 36 } + 10 sub check_num { + 11 my ($upstream, $cur_prime) = @_; + 12 my $kid; + 13 my $downstream = Thread::Queue->new(); + 14 while (my $num = $upstream->dequeue()) { + 15 next unless ($num % $cur_prime); + 16 if ($kid) { + 17 $downstream->enqueue($num); + 18 } else { + 19 print("Found prime: $num\n"); + 20 $kid = threads->create(\&check_num, $downstream, $num); + 21 if (! $kid) { + 22 warn("Sorry. Ran out of threads.\n"); + 23 last; + 24 } + 25 } + 26 } + 27 if ($kid) { + 28 $downstream->enqueue(undef); + 29 $kid->join(); + 30 } + 31 } + 32 + 33 my $stream = Thread::Queue->new(3..1000, undef); + 34 check_num($stream, 2); This program uses the pipeline model to generate prime numbers. Each thread in the pipeline has an input queue that feeds numbers to be @@ -868,33 +896,32 @@ number is, it's a number that's only evenly divisible by itself and 1.) The bulk of the work is done by the C subroutine, which takes a reference to its input queue and a prime number that it's responsible for. After pulling in the input queue and the prime that -the subroutine's checking (line 20), we create a new queue (line 22) +the subroutine is checking (line 11), we create a new queue (line 13) and reserve a scalar for the thread that we're likely to create later -(line 21). +(line 12). -The while loop from lines 23 to line 31 grabs a scalar off the input +The while loop from line 14 to line 26 grabs a scalar off the input queue and checks against the prime this thread is responsible -for. Line 24 checks to see if there's a remainder when we modulo the -number to be checked against our prime. If there is one, the number +for. Line 15 checks to see if there's a remainder when we divide the +number to be checked by our prime. If there is one, the number must not be evenly divisible by our prime, so we need to either pass -it on to the next thread if we've created one (line 26) or create a +it on to the next thread if we've created one (line 17) or create a new thread if we haven't. -The new thread creation is line 29. We pass on to it a reference to -the queue we've created, and the prime number we've found. +The new thread creation is line 20. We pass on to it a reference to +the queue we've created, and the prime number we've found. In lines 21 +through 24, we check to make sure that our new thread got created, and +if not, we stop checking any remaining numbers in the queue. Finally, once the loop terminates (because we got a 0 or C in the queue, which serves as a note to terminate), we pass on the notice to our -child and wait for it to exit if we've created a child (lines 32 and -35). +child, and wait for it to exit if we've created a child (lines 27 and +30). -Meanwhile, back in the main thread, we first create a queue (line 10) and -queue up all the numbers from 3 to 1000 for checking (lines 11-13), -plus a termination notice (line 14). Then we create the initial child -threads (line 16), passing it the queue and the first prime: 2. Finally, -we wait for the first child thread to terminate (line 17). Because a -child won't terminate until its child has terminated, we know that we're -done once we return from the C. +Meanwhile, back in the main thread, we first create a queue (line 33) and +queue up all the numbers from 3 to 1000 for checking, plus a termination +notice. Then all we have to do to get the ball rolling is pass the queue +and the first prime to the C subroutine (line 34). That's how it works. It's pretty simple; as with many Perl programs, the explanation is much longer than the program. @@ -999,7 +1026,7 @@ the root directory of all the threads changes, and no thread can undo it (as opposed to C). Further examples of process-scope changes include C and -changing uids/gids. +changing uids and gids. Thinking of mixing C and threads? Please lie down and wait until the feeling passes. Be aware that the semantics of C vary @@ -1020,7 +1047,9 @@ threads. See L for more details.) Whether various library calls are thread-safe is outside the control of Perl. Calls often suffering from not being thread-safe include: -C, C, C, C, +C, C, functions fetching user, group and +network information (such as C, C, +C and so on), C, C, and C -- in general, calls that depend on some global external state. @@ -1071,7 +1100,7 @@ Here's a short bibliography courtesy of J Birrell, Andrew D. An Introduction to Programming with Threads. Digital Equipment Corporation, 1989, DEC-SRC Research Report #35 online as -http://gatekeeper.dec.com/pub/DEC/SRC/research-reports/abstracts/src-rr-035.html +ftp://ftp.dec.com/pub/DEC/SRC/research-reports/SRC-035.pdf (highly recommended) Robbins, Kay. A., and Steven Robbins. Practical Unix Programming: A