結城浩
2003年3月15日
休日なので、 Perl 5.8.0のマルチスレッドプログラミングで遊ぶ。
use v5.8.0; use strict; use threads; my $thread1 = threads->new(\&main, "One"); my $thread2 = threads->new(\&main, "Two"); $thread1->join; $thread2->join; print "done.\n"; sub main { my ($name) = @_; for (1..10) { print "I am $name ($_)\n"; threads->yield(); } }
以下が実行例。
I am One (1) I am One (2) I am Two (1) I am One (3) I am Two (2) I am One (4) I am Two (3) I am One (5) I am Two (4) I am One (6) I am Two (5) I am One (7) I am Two (6) I am One (8) I am Two (7) I am One (9) I am Two (8) I am One (10) I am Two (9) I am Two (10) done.
Perl ithreadsの勉強のため、 自分で課題を出して、自分で解く。 Producer-Consumerのプログラム練習。
use strict; use threads; use threads::shared; my @queue : shared = (); my $queue_max : shared = 3; my $producer = threads->new(\&producer_main); my $consumer = threads->new(\&consumer_main); $producer->join; $consumer->join; print "done.\n"; sub producer_main { my $count = 10; while ($count >= 0) { lock(@queue); while (@queue >= $queue_max) { print "producer waits.\n"; cond_wait(@queue); } print "producer enqueues $count.\n"; push(@queue, $count); cond_broadcast(@queue); $count--; } print "producer_main ends.\n"; } sub consumer_main { my $count; do { lock(@queue); while (@queue == 0) { print "consumer waits.\n"; cond_wait(@queue); } $count = shift(@queue); print "consumer dequeues $count.\n"; cond_broadcast(@queue); } while $count > 0; print "consumer_main ends.\n"; }
実行例は以下。
producer enqueues 10. producer enqueues 9. producer enqueues 8. producer waits. consumer dequeues 10. producer enqueues 7. producer waits. consumer dequeues 9. producer enqueues 6. producer waits. consumer dequeues 8. consumer dequeues 7. consumer dequeues 6. consumer waits. producer enqueues 5. consumer dequeues 5. consumer waits. producer enqueues 4. producer enqueues 3. producer enqueues 2. producer waits. consumer dequeues 4. producer enqueues 1. producer waits. consumer dequeues 3. producer enqueues 0. producer_main ends. consumer dequeues 2. consumer dequeues 1. consumer dequeues 0. consumer_main ends. done.
実は、自分でwait¬ifyをしなくても、 Thread::Queueというモジュールを使うのがよろしいということを今日学ぶ。 そうすると、sharedなどを気にしなくてもよい。
use strict; use threads; use Thread::Queue; $| = 1; my $queue = new Thread::Queue; my $producer = threads->new(\&producer_main); my $consumer = threads->new(\&consumer_main); $producer->join; $consumer->join; print "\n"; print "done.\n"; sub producer_main { my $count = 100; while ($count >= 0) { $queue->enqueue($count); # print "producer enqueues $count.\n"; print "P"; $count--; } # print "producer_main ends.\n"; } sub consumer_main { my $count; do { $count = $queue->dequeue; # print "consumer dequeues $count.\n"; print "C"; } while $count > 0; # print "consumer_main ends.\n"; }
実行例は以下。
PPPPPPPPPPPPPPPPCCCCCCCCCCCCCCCCCPCPCPCPPPPPPPPPPPPPPPCCCCCCCCCCCCCCCPCPPPPPPPPP PPPPPPPPCCCCCCCCCCCCCCCCPPPPPPPPPPPPPPPPPPCCCCCCCCCCCCCCCCCCPPPPPPPPPPPPPPPPPPCC CCCCCCCCCCCCCCCCPPPPPPPPPPPPPCCCCCCCCCCCCC done.