使用 Thread::Semaphore。限制线程数
Work with Thread::Semaphore.Limit the number of threads
我无法处理Semapfor。由于他们运行,所以他们通过了一个流?实际上,变量$n Randomnaya取自0到2。当条件$n = $it(#$num - stream number)时,消息,则流$num抽烟。其他的(# where $ n!= $ Num)应该被跳过。消息"trade does not smoke."的情况是一下子把所有的线程都传过去了,在不需要的地方,他推导出流量$num冒烟(#其实给出了正确的数字,但是不符合情况) .
#! usr/bin/perl -w
use strict;
use warnings;
use 5.010;
use threads;
use threads::shared;
use Thread::Semaphore;
my $sem = Thread::Semaphore->new(1);
my $n = int rand(3);
say $n;
my $shr : shared = 1;
my $threads = 2;
my @threads;
for my $t ( 0 .. $threads ) {
push @threads, threads->create( \&smoke, $t );
}
# Дожидаемся окончания работы всех потоков
for my $t (@threads) { $t->join(); }
sub smoke {
my $num = shift;
$sem->down;
say "+Thread $num started";
sleep 1;
if ( $num = $n ) { sleep 2; say "Thread $num -- smoke"; }
say "-Thread $num done. \n";
if ( $num != $n ) {
say "-Thread $num dont smoke!. \n";
}
{ lock($shr); $shr++ }
$sem->up;
return;
sleep 1;
}
信号量并不比共享计数器复杂。
当您调用 down()
时,计数器会减少 - 如果不能减少,它将阻塞。如果您调用 up()
,则计数会增加。 (并且任何阻塞都将被释放)。
但是,在 'block' 发生之前,线程可以 - 并且将会 - 以未定义的顺序执行,您应该假设这是随机的。 (不完全是,但依赖任何特定序列都会产生竞争条件)。
这并不复杂,但 可能 使您陷入困境的其中一件事是缓冲 - 线程中的打印语句可能会被缓冲,因此似乎以奇怪的顺序到达。
例如:
#! usr/bin/perl -w
use strict;
use warnings;
use 5.010;
use threads;
use threads::shared;
use Thread::Semaphore;
my $sem = Thread::Semaphore->new(1);
#turn off buffering
$|++;
sub wait_for_sem {
print threads -> self -> tid. ": waiting for semaphore\n";
$sem -> down();
print threads -> self -> tid. ": got semaphore\n";
sleep rand 3;
print threads -> self -> tid. ": releasing semaphore\n";
$sem -> up;
}
threads -> create ( \&wait_for_sem ) for 1..100;
foreach my $thr ( threads -> list ) {
print "Waiting for ".$thr->tid." to join\n";
$thr -> join;
print "Joined ".$thr->tid."\n";
}
我认为缓冲是您的代码出了问题的地方 - 试试 $|++
。
我无法处理Semapfor。由于他们运行,所以他们通过了一个流?实际上,变量$n Randomnaya取自0到2。当条件$n = $it(#$num - stream number)时,消息,则流$num抽烟。其他的(# where $ n!= $ Num)应该被跳过。消息"trade does not smoke."的情况是一下子把所有的线程都传过去了,在不需要的地方,他推导出流量$num冒烟(#其实给出了正确的数字,但是不符合情况) .
#! usr/bin/perl -w
use strict;
use warnings;
use 5.010;
use threads;
use threads::shared;
use Thread::Semaphore;
my $sem = Thread::Semaphore->new(1);
my $n = int rand(3);
say $n;
my $shr : shared = 1;
my $threads = 2;
my @threads;
for my $t ( 0 .. $threads ) {
push @threads, threads->create( \&smoke, $t );
}
# Дожидаемся окончания работы всех потоков
for my $t (@threads) { $t->join(); }
sub smoke {
my $num = shift;
$sem->down;
say "+Thread $num started";
sleep 1;
if ( $num = $n ) { sleep 2; say "Thread $num -- smoke"; }
say "-Thread $num done. \n";
if ( $num != $n ) {
say "-Thread $num dont smoke!. \n";
}
{ lock($shr); $shr++ }
$sem->up;
return;
sleep 1;
}
信号量并不比共享计数器复杂。
当您调用 down()
时,计数器会减少 - 如果不能减少,它将阻塞。如果您调用 up()
,则计数会增加。 (并且任何阻塞都将被释放)。
但是,在 'block' 发生之前,线程可以 - 并且将会 - 以未定义的顺序执行,您应该假设这是随机的。 (不完全是,但依赖任何特定序列都会产生竞争条件)。
这并不复杂,但 可能 使您陷入困境的其中一件事是缓冲 - 线程中的打印语句可能会被缓冲,因此似乎以奇怪的顺序到达。
例如:
#! usr/bin/perl -w
use strict;
use warnings;
use 5.010;
use threads;
use threads::shared;
use Thread::Semaphore;
my $sem = Thread::Semaphore->new(1);
#turn off buffering
$|++;
sub wait_for_sem {
print threads -> self -> tid. ": waiting for semaphore\n";
$sem -> down();
print threads -> self -> tid. ": got semaphore\n";
sleep rand 3;
print threads -> self -> tid. ": releasing semaphore\n";
$sem -> up;
}
threads -> create ( \&wait_for_sem ) for 1..100;
foreach my $thr ( threads -> list ) {
print "Waiting for ".$thr->tid." to join\n";
$thr -> join;
print "Joined ".$thr->tid."\n";
}
我认为缓冲是您的代码出了问题的地方 - 试试 $|++
。