⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 perlothrtut.pod

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 POD
📖 第 1 页 / 共 3 页
字号:
=back=head2 Attributes: Restricting Access To SubroutinesIn addition to synchronizing access to data or resources, you mightfind it useful to synchronize access to subroutines.  You may beaccessing a singular machine resource (perhaps a vector processor), orfind it easier to serialize calls to a particular subroutine than tohave a set of locks and semaphores.One of the additions to Perl 5.005 is subroutine attributes.  TheThread package uses these to provide several flavors ofserialization.  It's important to remember that these attributes areused in the compilation phase of your program so you can't change asubroutine's behavior while your program is actually running.=head2 Subroutine LocksThe basic subroutine lock looks like this:    sub test_sub :locked {     }This ensures that only one thread will be executing this subroutine atany one time.  Once a thread calls this subroutine, any other threadthat calls it will block until the thread in the subroutine exitsit.  A more elaborate example looks like this:    use Thread qw(yield);     new Thread \&thread_sub, 1;     new Thread \&thread_sub, 2;     new Thread \&thread_sub, 3;     new Thread \&thread_sub, 4;    sub sync_sub :locked {         my $CallingThread = shift @_;         print "In sync_sub for thread $CallingThread\n";        yield;         sleep 3;         print "Leaving sync_sub for thread $CallingThread\n";     }    sub thread_sub {         my $ThreadID = shift @_;         print "Thread $ThreadID calling sync_sub\n";        sync_sub($ThreadID);         print "$ThreadID is done with sync_sub\n";     }The C<locked> attribute tells perl to lock sync_sub(), and if you runthis, you can see that only one thread is in it at any one time.=head2 MethodsLocking an entire subroutine can sometimes be overkill, especiallywhen dealing with Perl objects.  When calling a method for an object,for example, you want to serialize calls to a method, so that only onethread will be in the subroutine for a particular object, but threadscalling that subroutine for a different object aren't blocked.  Themethod attribute indicates whether the subroutine is really a method.    use Thread;    sub tester {         my $thrnum = shift @_;         my $bar = Foo->new();        foreach (1..10) { 	            print "$thrnum calling per_object\n";             $bar->per_object($thrnum); 	            print "$thrnum out of per_object\n";             yield;             print "$thrnum calling one_at_a_time\n";            $bar->one_at_a_time($thrnum); 	            print "$thrnum out of one_at_a_time\n";             yield;         }     }    foreach my $thrnum (1..10) {         new Thread \&tester, $thrnum;     }    package Foo;     sub new {         my $class = shift @_;         return bless [@_], $class;     }    sub per_object :locked :method {         my ($class, $thrnum) = @_;         print "In per_object for thread $thrnum\n";         yield;         sleep 2;         print "Exiting per_object for thread $thrnum\n";     }    sub one_at_a_time :locked {         my ($class, $thrnum) = @_;         print "In one_at_a_time for thread $thrnum\n";             yield;         sleep 2;         print "Exiting one_at_a_time for thread $thrnum\n";     }As you can see from the output (omitted for brevity; it's 800 lines)all the threads can be in per_object() simultaneously, but only onethread is ever in one_at_a_time() at once.=head2 Locking A SubroutineYou can lock a subroutine as you would lock a variable.  Subroutine lockswork the same as specifying a C<locked> attribute for the subroutine,and block all access to the subroutine for other threads until thelock goes out of scope.  When the subroutine isn't locked, any numberof threads can be in it at once, and getting a lock on a subroutinedoesn't affect threads already in the subroutine.  Getting a lock on asubroutine looks like this:    lock(\&sub_to_lock);Simple enough.  Unlike the C<locked> attribute, which is a compile timeoption, locking and unlocking a subroutine can be done at runtime at yourdiscretion.  There is some runtime penalty to using lock(\&sub) insteadof the C<locked> attribute, so make sure you're choosing the propermethod to do the locking.You'd choose lock(\&sub) when writing modules and code to run on boththreaded and unthreaded Perl, especially for code that will run on5.004 or earlier Perls.  In that case, it's useful to have subroutinesthat should be serialized lock themselves if they're running threaded,like so:    package Foo;     use Config;     $Running_Threaded = 0;    BEGIN { $Running_Threaded = $Config{'usethreads'} }    sub sub1 { lock(\&sub1) if $Running_Threaded }This way you can ensure single-threadedness regardless of whichversion of Perl you're running.=head1 General Thread Utility RoutinesWe've covered the workhorse parts of Perl's threading package, andwith these tools you should be well on your way to writing threadedcode and packages.  There are a few useful little pieces that didn'treally fit in anyplace else.=head2 What Thread Am I In?The Thread->self method provides your program with a way to get anobject representing the thread it's currently in.  You can use thisobject in the same way as the ones returned from the thread creation.=head2 Thread IDstid() is a thread object method that returns the thread ID of thethread the object represents.  Thread IDs are integers, with the mainthread in a program being 0.  Currently Perl assigns a unique tid toevery thread ever created in your program, assigning the first threadto be created a tid of 1, and increasing the tid by 1 for each newthread that's created.=head2 Are These Threads The Same?The equal() method takes two thread objects and returns true if the objects represent the same thread, and false if they don't.=head2 What Threads Are Running?Thread->list returns a list of thread objects, one for each threadthat's currently running.  Handy for a number of things, includingcleaning up at the end of your program:    # Loop through all the threads     foreach $thr (Thread->list) {         # Don't join the main thread or ourselves         if ($thr->tid && !Thread::equal($thr, Thread->self)) {             $thr->join;         }     }The example above is just for illustration.  It isn't strictlynecessary to join all the threads you create, since Perl detaches allthe threads before it exits.=head1 A Complete ExampleConfused yet? It's time for an example program to show some of thethings we've covered.  This program finds prime numbers using threads.    1  #!/usr/bin/perl -w    2  # prime-pthread, courtesy of Tom Christiansen    3    4  use strict;    5    6  use Thread;    7  use Thread::Queue;    8    9  my $stream = Thread::Queue->new();    10 my $kid    = Thread->new(\&check_num, $stream, 2);    11    12 for my $i ( 3 .. 1000 ) {    13     $stream->enqueue($i);    14 }     15    16 $stream->enqueue(undef);    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 = Thread->new(\&check_num, $downstream, $num);    30         }    31     }     32     $downstream->enqueue(undef) if $kid;    33     $kid->join()		if $kid;    34 }This program uses the pipeline model to generate prime numbers.  Eachthread in the pipeline has an input queue that feeds numbers to bechecked, a prime number that it's responsible for, and an output queuethat it funnels numbers that have failed the check into.  If the threadhas a number that's failed its check and there's no child thread, thenthe thread must have found a new prime number.  In that case, a newchild thread is created for that prime and stuck on the end of thepipeline.This probably sounds a bit more confusing than it really is, so letsgo through this program piece by piece and see what it does.  (Forthose of you who might be trying to remember exactly what a primenumber is, it's a number that's only evenly divisible by itself and 1)The bulk of the work is done by the check_num() subroutine, whichtakes a reference to its input queue and a prime number that it'sresponsible for.  After pulling in the input queue and the prime thatthe subroutine's checking (line 20), we create a new queue (line 22)and reserve a scalar for the thread that we're likely to create later(line 21).The while loop from lines 23 to line 31 grabs a scalar off the inputqueue and checks against the prime this thread is responsiblefor.  Line 24 checks to see if there's a remainder when we modulo thenumber to be checked against our prime.  If there is one, the numbermust not be evenly divisible by our prime, so we need to either passit on to the next thread if we've created one (line 26) or create anew thread if we haven't.The new thread creation is line 29.  We pass on to it a reference tothe queue we've created, and the prime number we've found.Finally, once the loop terminates (because we got a 0 or undef in thequeue, which serves as a note to die), we pass on the notice to ourchild and wait for it to exit if we've created a child (Lines 32 and37).Meanwhile, back in the main thread, we create a queue (line 9) and theinitial child thread (line 10), and pre-seed it with the first prime:2.  Then we queue all the numbers from 3 to 1000 for checking (lines12-14), then queue a die notice (line 16) and wait for the first childthread to terminate (line 17).  Because a child won't die until itschild has died, we know that we're done once we return from the join.That's how it works.  It's pretty simple; as with many Perl programs,the explanation is much longer than the program.=head1 ConclusionA complete thread tutorial could fill a book (and has, many times),but this should get you well on your way.  The final authority on howPerl's threads behave is the documentation bundled with the Perldistribution, but with what we've covered in this article, you shouldbe well on your way to becoming a threaded Perl expert.=head1 BibliographyHere's a short bibliography courtesy of J黵gen Christoffel:=head2 Introductory TextsBirrell, Andrew D. An Introduction to Programming withThreads. Digital Equipment Corporation, 1989, DEC-SRC Research Report#35 online ashttp://www.research.digital.com/SRC/staff/birrell/bib.html (highlyrecommended)Robbins, Kay. A., and Steven Robbins. Practical Unix Programming: AGuide to Concurrency, Communication, andMultithreading. Prentice-Hall, 1996.Lewis, Bill, and Daniel J. Berg. Multithreaded Programming withPthreads. Prentice Hall, 1997, ISBN 0-13-443698-9 (a well-writtenintroduction to threads).Nelson, Greg (editor). Systems Programming with Modula-3.  PrenticeHall, 1991, ISBN 0-13-590464-1.Nichols, Bradford, Dick Buttlar, and Jacqueline Proulx Farrell.Pthreads Programming. O'Reilly & Associates, 1996, ISBN 156592-115-1(covers POSIX threads).=head2 OS-Related ReferencesBoykin, Joseph, David Kirschen, Alan Langerman, and SusanLoVerso. Programming under Mach. Addison-Wesley, 1994, ISBN0-201-52739-1.Tanenbaum, Andrew S. Distributed Operating Systems. Prentice Hall,1995, ISBN 0-13-219908-4 (great textbook).Silberschatz, Abraham, and Peter B. Galvin. Operating System Concepts,4th ed. Addison-Wesley, 1995, ISBN 0-201-59292-4=head2 Other ReferencesArnold, Ken and James Gosling. The Java Programming Language, 2nded. Addison-Wesley, 1998, ISBN 0-201-31006-6.Le Sergent, T. and B. Berthomieu. "Incremental MultiThreaded GarbageCollection on Virtually Shared Memory Architectures" in MemoryManagement: Proc. of the International Workshop IWMM 92, St. Malo,France, September 1992, Yves Bekkers and Jacques Cohen, eds. Springer,1992, ISBN 3540-55940-X (real-life thread applications).=head1 AcknowledgementsThanks (in no particular order) to Chaim Frenkel, Steve Fink, GurusamySarathy, Ilya Zakharevich, Benjamin Sugars, J黵gen Christoffel, JoshuaPritikin, and Alan Burlison, for their help in reality-checking andpolishing this article.  Big thanks to Tom Christiansen for his rewriteof the prime number generator.=head1 AUTHORDan Sugalski E<lt>sugalskd@ous.eduE<gt>=head1 CopyrightsThis article originally appeared in The Perl Journal #10, and iscopyright 1998 The Perl Journal. It appears courtesy of Jon Orwant andThe Perl Journal.  This document may be distributed under the same termsas Perl itself.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -