2010-02-23 69 views
2

現在根據我在Perl ithreads下的理解,除非明確共享,否則所有數據都是私有的。如何在perl中調用每個線程狀態?

我想寫一個函數,它存儲每個線程狀態之間的調用。我認爲所有的數據在默認情況下是線程私有的副作用將允許我用這樣的封閉:當我運行它,這看起來像它的工作原理我所期望的方式

#!/usr/bin/perl -w 

use strict; 
use threads; 

{ # closure to create local static variable 
    my $per_thread_state = 0; 

    sub foo { 
     my $inc = shift; 
     $per_thread_state += $inc; 

     return $per_thread_state; 
    } 
} 

my $inc = 0; 

threads->create(
    sub { 
     my $inc = shift; 
     my $i = $inc; 
     while (--$i) { 
      threads->yield(); 
      print threads->tid().":".foo($inc)."\n"; 
     } 
    }, $inc 
) while (++$inc < $ARGV[0]); 

$_->join() foreach threads->list(); 

,但我只是想可以肯定,因爲我找不到任何明確討論這樣做的文檔。

任何人都可以指點我正式看的東西嗎?

編輯

,似乎奇怪的一件事是,線程似乎總是在創造的順序運行,並且不交錯的某些原因。例如,如果我運行:

./tsd.pl 100 

所有東西都按順序打印出來。如果它很重要,我在Ubuntu 9.04上。

+1

@Zaid:作爲一般規則,我通常只在24小時後接受答案。有一些耐心:-) – 2010-02-23 18:26:44

回答

2

假設你運行的是Perl 5.9.4+,這似乎是使用state關鍵字的一個好選擇。如果啓用了state,則只有您的foo()子例程將能夠修改值$per_thread_state

方法如下:

use feature 'state'; 

sub foo { 
    state $per_thread_state; 
    my $inc = shift; 
    $per_thread_state += $inc; 
    return $per_thread_state; 
} 

記住,使state雖然(從perlsub):

用Perl 5.9.4開始,你可以在我處的聲明與國家關鍵字變量。但是,爲了達到這個目的,您必須事先啓用該功能,或者使用功能編譯指示,或者在單線上使用-E。

perlsub也有關於Persistent Private Variable with Closures的部分。你所做的似乎很好。

+0

是的,我想保持兼容較舊的5.9.4 Perls。只是爲了確保'BEGIN'只有在我將「main」線程的代碼放在文件尾部時才需要,是正確的? – 2010-02-23 10:28:16

+0

實際上,是的,儘管我會把BEGIN寫在裏面 – Zaid 2010-02-23 10:51:09

1

您創建每個線程狀態的方法是正確的。

將Perl的線程視爲處理IPC和分叉進程的更方便的方法通常是有幫助的。每次撥打threads->create(...)都會克隆當前的翻譯器及其中的所有內容,因此每個線程都將獲得自己的獨立副本foo()$per_thread_state。當你加入一個線程時,你可以傳回一個值,但是線程解釋器狀態下的所有內容都將被銷燬。

你的線程在創建順序主要是由於在Perl實現細節和操作系統(主要是因爲他們個人的執行時間是操作系統的最短運行時間片段下文)運行。要交叉線程,可以使用sleep而不是yield(或使線程完成一些實際工作)。

+0

時間片是有意義的。我在循環100次的'foo'中增加了一個乘法和除法,現在我看到了更一致的交錯。 – 2010-02-24 05:58:24

+0

@Eric:我想你可以回答這個問題:http://stackoverflow.com/questions/2317507/why-do-my-perl-threads-execute-randomly-on-the-first-run-but-in階上,subseque – 2010-02-24 06:20:15