サンタクロース問題(マルチスレッドのお勉強)
初出はちょっと前だが、時期的には丁度いいのかなと。
http://karetta.jp/article/blog/oneline/030756
問題文には、どんなタイミングでトナカイや小人が戻ってくるかは明記されていない。ので、そこはランダム間隔なんだろう。(他の言語のを見てもそうなってた)。
要するに、マルチスレッドの練習問題な訳だ。
まあ、CGI作る分にはマルチスレッドはあんまり関係ない訳だが、できないよりはできる方がいいのでやってみた。
santa.pl
use strict; use threads; use threads::shared; # トナカイの名前 my @rangifer_name = qw ( Dasher Dancer Prancer Vixen Donder Blitzen Cupid Comet Rudolph ); # 小人の名前 my @gnome_name = qw ( Bashfun Grumpy Happy Sleepy Dopey Sneezy Doc eight nine ten ); # 準備 my @returned_rangifer : shared = (); my @returned_gnome : shared = (); my $count : shared = 0; # 開始 my $santa = threads->new(\&santa); $santa->join; exit; # サンタ sub santa { my %rangifer = map { $_=>threads->new(\&rangifer, $_) } @rangifer_name; my %gnome = map { $_=>threads->new(\&gnome, $_) } @gnome_name; my $mode = -1; while ( $count < 100000 ) { my $r = scalar @returned_rangifer; my $d = scalar @returned_gnome; if ( 2 < $d ) { print "$count : Santa and $d gnomes are Talking.\n"; foreach ( 1..$d ) { my $name = shift @returned_gnome; $gnome{$name}->join; $gnome{$name} = threads->new(\&gnome, $name); } $mode = 2; } elsif ( 8 < $r ) { print "$count : Santa and $r rangifers are Flying.\n"; foreach ( 1..$r ) { my $name = shift @returned_rangifer; $rangifer{$name}->join; $rangifer{$name} = threads->new(\&rangifer, $name); } $mode = 1; } else { $mode == 0 or print "$count : Santa is Sleeping.\n"; $mode = 0; } ++ $count; } } # トナカイ sub rangifer { my $name = shift; select undef, undef, undef, rand(); print "$count : rangifer - $name Return\n"; ++ $count; push @returned_rangifer, $name; } # 小人 sub gnome { my $name = shift; select undef, undef, undef, rand(); print "$count : gnome - $name Return\n"; ++ $count; push @returned_gnome, $name; }
実行結果
0 : rangifer - Rudolph Return 1 : Santa is Sleeping. 1306 : gnome - nine Return 3360 : gnome - Happy Return 7701 : gnome - ten Return 7703 : Santa and 3 gnomes are Talking. 7703 : gnome - Grumpy Return 7705 : Santa is Sleeping. 16128 : gnome - Dopey Return 18262 : rangifer - Blitzen Return 27867 : gnome - Bashfun Return 27868 : Santa and 3 gnomes are Talking. 27868 : rangifer - Cupid Return 27869 : rangifer - Prancer Return 27871 : Santa is Sleeping. 28457 : rangifer - Dancer Return 35750 : rangifer - Donder Return 47049 : gnome - Happy Return 62917 : gnome - Sneezy Return 66219 : rangifer - Comet Return 66378 : rangifer - Vixen Return 70658 : gnome - eight Return 78392 : rangifer - Dasher Return 79805 : Santa and 3 gnomes are Talking. 79806 : Santa and 9 rangifers are Flying. 79806 : gnome - Dopey Return 79807 : gnome - Sleepy Return 79808 : gnome - Bashfun Return 79809 : gnome - ten Return 79810 : gnome - Doc Return 79812 : Santa and 5 gnomes are Talking. 79813 : Santa is Sleeping. 94181 : gnome - nine Return 98901 : gnome - Sleepy Return A thread exited while 18 threads were running.
最後に警告メッセージが出ててまあ、お行儀の悪いこと。
つうか、これどうやっても出たりしない?