<<=========================threads===========================>>
print ( 'Thread
started: ' , join ( '
' , @args ), "\n" );
|
my $thr =
threads->create( 'start_thread' , 'argument1' , 'argument2' );
|
threads->create( sub { print ( "I
am a thread\n" );
})-> join ();
|
my $thr2 =
async { foreach ( @ARGS )
{ print "$_\n" ;
} };
|
if ( my $err = $thr2 ->error())
{
|
warn ( "Thread
error: $err\n" );
|
my $thr3 =
threads->create( sub { return (qw/a
b c/); });
|
my $thr4 =
threads->create({ 'context' => 'list' },
|
sub { return (qw/a
b c/); });
|
my @results = $thr3 -> join ();
|
$thr7 =
threads->object( $tid );
|
my @threads =
threads->list();
|
my $thread_count =
threads->list();
|
my @running =
threads->list(threads::running);
|
my @joinable =
threads->list(threads::joinable);
|
print "thread4
equals to thread2.\n" ;
|
$stack_size =
threads->get_stack_size();
|
$old_size =
threads->set_stack_size(32*4096);
|
my $thr5 =
threads->create({ 'context' => 'list' ,
|
my $wantarray = $thr -> wantarray ();
|
if ( $thr5 ->is_running())
{
|
if ( $thr5 ->is_joinable())
{
|
<<=========================Thread========================>>
$thread = Thread->new(\&start_sub)
$thread = Thread->new(\&start_sub,@args)
start_sub指定线程要执行的子例程,args是传给子例程的参数。
lock VARIABLE
给变量加锁,直到锁超出范围。给变量加锁只影响到lock函数的调用--即一个线程lock var1后,另一个线程再调用lovk var1时线程就会阻塞,但lock VARIABLE并不影响正常的对变量的访问。
如果锁往的是一个容器(如哈希或数组),那么其中的每一个元素并没有全部被锁住。比如一个线程中调用lock @arr,在另一个线程中调用lock $arr[3]时并不会阻塞。
async BLOCK;
async函数创建并返回一个线程实例,该线程要执行的代码全在BLOCK中,这里BLOCK是个匿名子例程,所以其后一定加分号。
Thread->self
返回调用Thread->self函数的线程实例。
Thread->list
返回non-joined和non-detached线程实例。
cond_waitLOCKED_VARIALBLE
cond_signal LOCKED_VARIALBLE
cond_broadcast LOCKED_VARIALBLE
上面3个函数主要用于线程问同步,都以一个已加锁的变量作为输入参数。当一个线程调用cond_wait后阻塞自己;当一个线程发出cond_broadcast后所有阻塞的线程得救;当一个线程发出cond_signal后只有一个阻塞的线程得救,至于是哪一个由系统内部决定。当然只有LOCKED_VARIALBLE参数相同时才为一组,大家才可以在一起玩同步。
yield
把CPU控制权交给另外一个线程,至于是哪个线程依赖于当时的运行环境。
join
等待一个线程结束并返回该线程结束时的返回值。
detach
分离的线程不允许被join。
equal
判断两个线程是否相同。
tid
返回线程的tid。tid是递增的,main线程的tid为0。
done
判断线程是否已经结束。
下面这3个函数在5005threads中还可以用,但是在ithreads中已经不可用了。
lock(\&sub) eval flags
<<============================threads::shared============================>>
默认下数据都是线程私有的,新创建的线程获得已有变量的一份私有拷贝。threads::shared用于在线程之间共享数据结构,可共享的数据类型只有6种,标量数据、数组、散列、以及它们的引用。
声明共享变量:
my ($scalar, @array, %hash);
share($scalar);
share(@array);
share(%hash);
share函数返回共享的值,这通常是一个引用。
也可以在编译时标记变量为共享变量:
my ($var, %hash, @array) :shared;
my ( $var , %hash , @array )
:shared;
|
shared_clone REF
my $obj = {'foo' => [qw/foo bar baz/]};
bless($obj, 'Foo');
my $cpy = shared_clone($obj);
# Object status (i.e., the class an object is blessed into) is also cloned.
print(ref($cpy), "\n"); # Outputs 'Foo'
对于克隆空的数组或散列,下面用法是等价的:
$var = &share([]); # Same as $var = shared_clone([]);
$var = &share({}); # Same as $var = shared_clone({});
is_shared VARIABLE
判断变量是否为共享变量,如果是则返回变量的内部ID(类似于refaddr函数),如果不是返回undef。
如果is_shared参数是数组或散列,它并不检查容器中的元素是否为共享变量。如下
print ( "\%hash
is shared\n" );
|
if (is_shared( $hash { 'elem' }))
{
|
print ( "\$hash{'elem'}
is in a shared hash\n" );
|
lock VARIABLE
不能对容器内部的变量进行加锁:
my %hash :shared;
$hash{'foo'} = 'bar';
#lock($hash{'foo'}); # Error
lock(%hash); # Works
cond_wait VARIABLE
cond_signal VARIABLE
cond_broadcast VARIABLE
这3个函数就不说了,跟threads里的一样。
cond_wait CONDVAR, LOCKVAR
当有其他线程signal第一个参数变量CONDVAR时,第二个参数变量LOCKVAR被解锁。
cond_timedwait VARIABLE, ABS_TIMEOUT
cond_timedwait CONDVAR, ABS_TIMEOUT, LOCKVAR
如果signal未到达,而timeout了,同样会把变量解锁。
my $foo :shared
= shared_clone({});
|
my $bar :shared
= shared_clone({});
|
print ( ref ( $foo ->{ 'bar' }), "\n" );
|
注意:如果你还想使用threads,那么你必须在"use threads::shared"
之前就"use threads",否则会报告异常。
如果你把一个数组、散列或它们的引用share以后,那么容器中的元素都会丢失。
print ( "ERROR:
\$foo is empty\n" )
|
if (! exists ( $foo ->{ 'data' }));
|
所以正确的做法是你应该先把一个空的容器share,然后再往里面添加元素。
<<========================Thread::Semaphore=============================>>
my $s =
Thread::Semaphore->new();
|
my $s =
Thread::Semaphore->new( $initial_value );
|
if ( $s ->down_nb( $down_value ))
{
|
$s ->down_force( $down_value );
|
<<===========================Thread::Queue===================================>>
直接看程序是学习语言的快速方法,注释得很清楚:
07
|
my $q =
Thread::Queue->new();
|
10
|
my $thr =
threads->create( sub {
|
11
|
while ( my $item = $q ->dequeue())
{
|
17
|
$q ->enqueue( $item1 ,
...);
|
21
|
my $left = $q ->pending();
|
24
|
if ( defined ( my $item = $q ->dequeue_nb()))
{
|
32
|
$q ->insert(1, $item1 , $item2 );
|
35
|
my ( $item1 , $item2 )
= $q ->extract(-2,
2);
|
上面代码中出现过的函数我就不介绍了。
下面的数据类型可以放入队列:
普通标题数据;
标量引用;
数组引用;
哈希引用;
以上对象的组合。
my @ary = qw/foo bar baz/;
$q->enqueue(\@ary); ##copy the elements 'foo', 'bar' and 'baz' from @ary into $q。
而对于共享变量,是它的引用进入队列,而没有发生元素的深复制。
my @ary :shared
= qw/foo bar baz/;
|
->new() ##创建新队列
->new(LIST) ##创建队列时压入元素
->enqueue(LIST) #入队
->dequeue() #从队中取出一个元素
->dequeue(COUNT) #从队中取出COUNT个元素,如果COUNT大于队列长度,则阻塞,下面的方法不会阻塞。
->dequeue_nb()
->dequeue_nb(COUNT)
->pending()
返回队列中元素的个数。
->peek() #取出队首元素,并没有出险
->peek(INDEX) #取出指定下标的队列元素,INDEX为负数时是从队尾开始数起
->insert(INDEX,LIST) #在指定的位置上插入一组元素,队首元素的INDEX为0
->extract()
->extract(INDEX)
->extract(INDEX, COUNT)
删除并返回指定的元素。