並列処理

forkするよりthreadを使ったほうが便利っぽい。
なぜか。
変数の共有も簡単。排他制御もできる。
forkしてパイプで・・・とか考えなくていいのです。
今日からforkしないでthreadsすることにします。


というわけで、threadsモジュールを触る。
もちろんスーパーチラシ裏タイム。
メモ専用wikiを作ってあるのに、日記のネタがないからこっちに書くとか、
いや何の意味もないよねぇ〜


threads関連のモジュールたち

自分なりに解釈してみた

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したときなどは、
排他制御が行われなくなるので、処理が終わらなくなる。