forkするよりthreadを使ったほうが便利っぽい。
なぜか。
変数の共有も簡単。排他制御もできる。
forkしてパイプで・・・とか考えなくていいのです。
今日からforkしないでthreadsすることにします。
というわけで、threadsモジュールを触る。
もちろんスーパーチラシ裏タイム。
メモ専用wikiを作ってあるのに、日記のネタがないからこっちに書くとか、
いや何の意味もないよねぇ〜
threads関連のモジュールたち
- threads
- threads::shared
- Thread::Queue
- http://perldoc.jp/docs/modules/Thread-2.00/Thread/Queue.pod
- スレッド間で安全に変数を受け渡しできるキュー
- Thread::Semaphore
自分なりに解釈してみた
threads
threads->new(\&func, @argv);
スレッドを生成する。関数のリファレンスとその関数に渡す引数を指定する。
threads->createでも同じことが可能。(newはcreateのエイリアス)
threads->list();
>joinおよびdetachされていない全てのスレッドのリストを返す。
スレッドの処理が終わるのを待つ時などに使える。
threads->yield();
他のスレッドにCPUを譲る事を許可する。
sleepしたりすると、その間は他のスレッドに優先するので効果のほどがわからない。
(重い処理でやったとしても、結局は後回しにしているだけなので、処理する時間は変わらない。)
threads::shared
まず、
use threads;
use threads::shared;
というように、use threads;の後に書かなければならない。
my $x : shared = 0;
$xはスレッド間の共有変数になる。
どのスレッド間から$xを参照しても共有された同じ$xを参照したような形になる。
ただ、排他制御は行われないため、
$x=0の時、2つのスレッドから$x++をされた後の$xが$x==2である保障はない。
共有できるものにスカラー、リスト、ハッシュ、そのリファレンスがある。
他色々多くて混乱中。そのうちメモる。
変数の排他制御とかできるらしい。Thread::Semaphoreとの区別をつけたい。
Thread::Queue
http://perldoc.jp/docs/modules/Thread-2.00/Thread/Queue.pod
スレッドセーフなキュー。
スレッドからのエンキューをしっかり待ってくれるオブジェクトが作れる。
ここの解説で十分。
Thread::Semaphore
my $s = new Thread::Semaphore()
スレッドセーフな排他制御を実現するオブジェクトを作る。
サンプル
my $sem = new Thread::Semaphore() foreach(1..10){ threads->new(\&func, $sem, $_); } # スレッドで呼ばれる関数 sub func{ my $s = shift; my $n = shift; $s->down; # if($n==3) {die;} # やってはいけない! #〜処理〜 $s->up; }
〜処理〜の部分が終わるまで他のスレッドは処理に入れる事は無い。
1から10までの番号を順番にスレッド処理をするが、
処理の部分がこの番号通りの順序で行われる保証はない。
またコメントアウトしてある箇所のように、排他制御中にdieしたときなどは、
排他制御が行われなくなるので、処理が終わらなくなる。