Perlでマルチスレッド

結城浩

2003年3月15日

2003年3月15日 (土) - Perl ithreads

休日なので、 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.

2003年3月17日 (月) - Perl ithreadsを使ったProducer-Consumer

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.

2003年3月20日 (木) - Thread::Queueを使ったProducer-Consumer

実は、自分でwait&notifyをしなくても、 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.