perlothrtut.1
来自「视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.」· 1 代码 · 共 1,197 行 · 第 1/4 页
1
1,197 行
DecThreads, or Java's Green threads, or Win32 threads. There aresimilarities, and the broad concepts are the same, but if you startlooking for implementation details you're going to be eitherdisappointed or confused. Possibly both..PPThis is not to say that Perl threads are completely different fromeverything that's ever come before\*(--they're not. Perl's threadingmodel owes a lot to other thread models, especially \s-1POSIX\s0. Just asPerl is not C, though, Perl threads are not \s-1POSIX\s0 threads. So if youfind yourself looking for mutexes, or thread priorities, it's time tostep back a bit and think about what you want to do and how Perl cando it..SH "Threadsafe Modules".IX Header "Threadsafe Modules"The addition of threads has changed Perl's internalssubstantially. There are implications for people who writemodules\*(--especially modules with \s-1XS\s0 code or external libraries. Whilemost modules won't encounter any problems, modules that aren'texplicitly tagged as thread-safe should be tested before being used inproduction code..PPNot all modules that you might use are thread-safe, and you shouldalways assume a module is unsafe unless the documentation saysotherwise. This includes modules that are distributed as part of thecore. Threads are a beta feature, and even some of the standardmodules aren't thread-safe..PPIf you're using a module that's not thread-safe for some reason, youcan protect yourself by using semaphores and lots of programmingdiscipline to control access to the module. Semaphores are coveredlater in the article. Perl Threads Are Different.SH "Thread Basics".IX Header "Thread Basics"The core Thread module provides the basic functions you need to writethreaded programs. In the following sections we'll cover the basics,showing you what you need to do to create a threaded program. Afterthat, we'll go over some of the features of the Thread module thatmake threaded programming easier..Sh "Basic Thread Support".IX Subsection "Basic Thread Support"Thread support is a Perl compile-time option-it's something that'sturned on or off when Perl is built at your site, rather than whenyour programs are compiled. If your Perl wasn't compiled with threadsupport enabled, then any attempt to use threads will fail..PPRemember that the threading support in 5.005 is in beta release, andshould be treated as such. You should expect that it may not functionentirely properly, and the thread interface may well change somebefore it is a fully supported, production release. The beta versionshouldn't be used for mission-critical projects. Having said that,threaded Perl is pretty nifty, and worth a look..PPYour programs can use the Config module to check whether threads areenabled. If your program can't run without them, you can say somethinglike:.PP.Vb 1\& $Config{usethreads} or die "Recompile Perl with threads to run this program.";.Ve.PPA possibly-threaded program using a possibly-threaded module mighthave code like this:.PP.Vb 2\& use Config; \& use MyMod; \&\& if ($Config{usethreads}) { \& # We have threads \& require MyMod_threaded; \& import MyMod_threaded; \& } else { \& require MyMod_unthreaded; \& import MyMod_unthreaded; \& }.Ve.PPSince code that runs both with and without threads is usually prettymessy, it's best to isolate the thread-specific code in its ownmodule. In our example above, that's what MyMod_threaded is, and it'sonly imported if we're running on a threaded Perl..Sh "Creating Threads".IX Subsection "Creating Threads"The Thread package provides the tools you need to create newthreads. Like any other module, you need to tell Perl you want to useit; use Thread imports all the pieces you need to create basicthreads..PPThe simplest, straightforward way to create a thread is with \fInew()\fR:.PP.Vb 1\& use Thread; \&\& $thr = Thread\->new( \e&sub1 );\&\& sub sub1 { \& print "In the thread\en"; \& }.Ve.PPThe \fInew()\fR method takes a reference to a subroutine and creates a newthread, which starts executing in the referenced subroutine. Controlthen passes both to the subroutine and the caller..PPIf you need to, your program can pass parameters to the subroutine aspart of the thread startup. Just include the list of parameters aspart of the \f(CW\*(C`Thread::new\*(C'\fR call, like this:.PP.Vb 5\& use Thread; \& $Param3 = "foo"; \& $thr = Thread\->new( \e&sub1, "Param 1", "Param 2", $Param3 );\& $thr = Thread\->new( \e&sub1, @ParamList );\& $thr = Thread\->new( \e&sub1, qw(Param1 Param2 $Param3) );\&\& sub sub1 { \& my @InboundParameters = @_; \& print "In the thread\en"; \& print "got parameters >", join("<>", @InboundParameters), "<\en"; \& }.Ve.PPThe subroutine runs like a normal Perl subroutine, and the call to newThread returns whatever the subroutine returns..PPThe last example illustrates another feature of threads. You can spawnoff several threads using the same subroutine. Each thread executesthe same subroutine, but in a separate thread with a separateenvironment and potentially separate arguments..PPThe other way to spawn a new thread is with \fIasync()\fR, which is a way tospin off a chunk of code like \fIeval()\fR, but into its own thread:.PP.Vb 1\& use Thread qw(async);\&\& $LineCount = 0; \&\& $thr = async { \& while(<>) {$LineCount++} \& print "Got $LineCount lines\en";\& }; \&\& print "Waiting for the linecount to end\en"; \& $thr\->join; \& print "All done\en";.Ve.PPYou'll notice we did a use Thread qw(async) in that example. async isnot exported by default, so if you want it, you'll either need toimport it before you use it or fully qualify it asThread::async. You'll also note that there's a semicolon after theclosing brace. That's because \fIasync()\fR treats the following block as ananonymous subroutine, so the semicolon is necessary..PPLike \fIeval()\fR, the code executes in the same context as it would if itweren't spun off. Since both the code inside and after the async startexecuting, you need to be careful with any shared resources. Lockingand other synchronization techniques are covered later..Sh "Giving up control".IX Subsection "Giving up control"There are times when you may find it useful to have a threadexplicitly give up the \s-1CPU\s0 to another thread. Your threading packagemight not support preemptive multitasking for threads, for example, oryou may be doing something compute-intensive and want to make surethat the user-interface thread gets called frequently. Regardless,there are times that you might want a thread to give up the processor..PPPerl's threading package provides the \fIyield()\fR function that doesthis. \fIyield()\fR is pretty straightforward, and works like this:.PP.Vb 10\& use Thread qw(yield async); \& async { \& my $foo = 50; \& while ($foo\-\-) { print "first async\en" }\& yield; \& $foo = 50; \& while ($foo\-\-) { print "first async\en" } \& }; \& async { \& my $foo = 50; \& while ($foo\-\-) { print "second async\en" }\& yield; \& $foo = 50; \& while ($foo\-\-) { print "second async\en" } \& };.Ve.Sh "Waiting For A Thread To Exit".IX Subsection "Waiting For A Thread To Exit"Since threads are also subroutines, they can return values. To waitfor a thread to exit and extract any scalars it might return, you canuse the \fIjoin()\fR method..PP.Vb 2\& use Thread; \& $thr = Thread\->new( \e&sub1 );\&\& @ReturnData = $thr\->join; \& print "Thread returned @ReturnData"; \&\& sub sub1 { return "Fifty\-six", "foo", 2; }.Ve.PPIn the example above, the \fIjoin()\fR method returns as soon as the threadends. In addition to waiting for a thread to finish and gathering upany values that the thread might have returned, \fIjoin()\fR also performsany \s-1OS\s0 cleanup necessary for the thread. That cleanup might beimportant, especially for long-running programs that spawn lots ofthreads. If you don't want the return values and don't want to waitfor the thread to finish, you should call the \fIdetach()\fR methodinstead. \fIdetach()\fR is covered later in the article..Sh "Errors In Threads".IX Subsection "Errors In Threads"So what happens when an error occurs in a thread? Any errors thatcould be caught with \fIeval()\fR are postponed until the thread isjoined. If your program never joins, the errors appear when yourprogram exits..PPErrors deferred until a \fIjoin()\fR can be caught with \fIeval()\fR:.PP.Vb 8\& use Thread qw(async); \& $thr = async {$b = 3/0}; # Divide by zero error\& $foo = eval {$thr\->join}; \& if ($@) { \& print "died with error $@\en"; \& } else { \& print "Hey, why aren\*(Aqt you dead?\en"; \& }.Ve.PP\&\fIeval()\fR passes any results from the joined thread back unmodified, soif you want the return value of the thread, this is your only chanceto get them..Sh "Ignoring A Thread".IX Subsection "Ignoring A Thread"\&\fIjoin()\fR does three things: it waits for a thread to exit, cleans upafter it, and returns any data the thread may have produced. But whatif you're not interested in the thread's return values, and you don'treally care when the thread finishes? All you want is for the threadto get cleaned up after when it's done..PPIn this case, you use the \fIdetach()\fR method. Once a thread is detached,it'll run until it's finished, then Perl will clean up after itautomatically..PP.Vb 2\& use Thread; \& $thr = Thread\->new( \e&sub1 ); # Spawn the thread\&\& $thr\->detach; # Now we officially don\*(Aqt care any more\&\& sub sub1 { \& $a = 0; \& while (1) { \& $a++; \& print "\e$a is $a\en"; \& sleep 1; \& } \& }.Ve.PPOnce a thread is detached, it may not be joined, and any output thatit might have produced (if it was done and waiting for a join) islost..SH "Threads And Data".IX Header "Threads And Data"Now that we've covered the basics of threads, it's time for our nexttopic: data. Threading introduces a couple of complications to dataaccess that non-threaded programs never need to worry about..Sh "Shared And Unshared Data".IX Subsection "Shared And Unshared Data"The single most important thing to remember when using threads is thatall threads potentially have access to all the data anywhere in yourprogram. While this is true with a nonthreaded Perl program as well,it's especially important to remember with a threaded program, sincemore than one thread can be accessing this data at once..PPPerl's scoping rules don't change because you're using threads. If asubroutine (or block, in the case of \fIasync()\fR) could see a variable ifyou weren't running with threads, it can see it if you are. This isespecially important for the subroutines that create, and makes \f(CW\*(C`my\*(C'\fRvariables even more important. Remember\*(--if your variables aren'tlexically scoped (declared with \f(CW\*(C`my\*(C'\fR) you're probably sharing thembetween threads..Sh "Thread Pitfall: Races".IX Subsection "Thread Pitfall: Races"While threads bring a new set of useful tools, they also bring anumber of pitfalls. One pitfall is the race condition:.PP.Vb 4\& use Thread; \& $a = 1; \& $thr1 = Thread\->new(\e&sub1); \& $thr2 = Thread\->new(\e&sub2); \&\& sleep 10; \& print "$a\en";\&
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?