0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

perl のスレッドで変数を共有する

Last updated at Posted at 2022-05-01

スレッド間でデータの共有が必要と言うことで試してみた。

普通の変数をスレッド間で共有

a.pl
#!/opt/perl-5.34.1/bin/perl5.34.1
use threads;
use threads::shared;

my $share_data : shared = 1;

my $thread_a = threads->create(\&sub_a , 10); sleep 2;
my $thread_b = threads->create(\&sub_a , 20); sleep 2;
my $thread_c = threads->create(\&sub_a , 30); sleep 2;

$thread_a->join();
$thread_b->join();
$thread_c->join();

sub sub_a {
        $share_data = shift ;
        printf "th %d start, num %d\n", threads->self->tid(), $share_data;
        sleep 3;
        $share_data += 5;
        printf "th %d done , num %d\n", threads->self->tid(), $share_data;
}
実行結果
% ./a.pl
th 1 start, num 10
th 2 start, num 20
th 1 done , num 25
th 3 start, num 30
th 2 done , num 35
th 3 done , num 40

最後の th 3 なんかが分かりやすいですが、最初 30 だったのに、th 2 に +5 されて、自分でも +5 して 40 になってますね。
なるほど、ちゃんと変数の値が共有できてます。

配列のスレッド間共有

b.pl
#!/opt/perl-5.34.1/bin/perl5.34.1
use threads;
use threads::shared;

my @share_data : shared = 1;
@share_data = ();

my $thread_a = threads->create(\&sub_a , 10); sleep 2;
my $thread_b = threads->create(\&sub_a , 20); sleep 2;
my $thread_c = threads->create(\&sub_a , 30); sleep 2;

$thread_a->join();
$thread_b->join();
$thread_c->join();

sub sub_a {
        @share_data[1] = shift ;
        printf "th %d start, num %d\n", threads->self->tid(), $share_data[1];
        sleep 3;
        @share_data[1] += 5;
        printf "th %d done , num %d\n", threads->self->tid(), $share_data[1];
}

実行!

実行結果
% ./b.pl
th 1 start, num 10
th 2 start, num 20
th 1 done , num 25
th 3 start, num 30
th 2 done , num 35
th 3 done , num 40

これも共有できてる。

配列のリファレンスをスレッド間で共有

マニュアルにあるので、若干不思議な宣言方法ですけども

ref.pl
#!/opt/perl-5.34.1/bin/perl5.34.1
use strict;
use warnings;
use threads;
use threads::shared;

my $share_data = &share([]);

$share_data->[1] = 0;

my $thread_a = threads->create(\&sub_a , 10); sleep 2;
my $thread_b = threads->create(\&sub_a , 20); sleep 2;
my $thread_c = threads->create(\&sub_a , 30); sleep 2;

$thread_a->join();
$thread_b->join();
$thread_c->join();

sub sub_a {
        $share_data->[1] = shift ;
        printf "th %d start, num %d\n", threads->self->tid(), $share_data->[1];
        sleep 3;
        $share_data->[1] += 5;
        printf "th %d done , num %d\n", threads->self->tid(), $share_data->[1];
}
実行結果
% ./ref.pl
th 1 start, num 10
th 2 start, num 20
th 1 done , num 25
th 3 start, num 30
th 2 done , num 35
th 3 done , num 40

共有できてる。

配列のリファレンス (2次元) をスレッド間で共有

ref2.pl
#!/opt/perl-5.34.1/bin/perl5.34.1
use threads;
use threads::shared;

my $share_data : shared = 1;
$share_data->[1] = [0, 0];

my $thread_a = threads->create(\&sub_a , 10); sleep 2;
my $thread_b = threads->create(\&sub_a , 20); sleep 2;
my $thread_c = threads->create(\&sub_a , 30); sleep 2;

$thread_a->join();
$thread_b->join();
$thread_c->join();

sub sub_a {
        $share_data->[1][1] = shift ;
        printf "th %d start, num %d\n", threads->self->tid(), $share_data->[1][1];
        sleep 3;
        $share_data->[1][1] += 5;
        printf "th %d done , num %d\n", threads->self->tid(), $share_data->[1][1];
}

実行結果

実行結果
% ./ref2.pl
th 1 start, num 10
th 2 start, num 20
th 1 done , num 15
th 3 start, num 30
th 2 done , num 25
th 3 done , num 35

done は必ず start の +5 になってますね。どうやら独立している模様。

配列のリファレンス (2次元) をスレッド間で共有 その2

ref3.pl
#!/opt/perl-5.34.1/bin/perl5.34.1
use strict;
use warnings;
use threads;
use threads::shared;

my $share_data = &share([]);

$share_data->[0] = &share([]);
$share_data->[1] = &share([]);

$share_data->[1][1] = 0;

my $thread_a = threads->create(\&sub_a , 10); sleep 2;
my $thread_b = threads->create(\&sub_a , 20); sleep 2;
my $thread_c = threads->create(\&sub_a , 30); sleep 2;

$thread_a->join();
$thread_b->join();
$thread_c->join();

sub sub_a {
        $share_data->[1][1] = shift ;
        printf "th %d start, num %d\n", threads->self->tid(), $share_data->[1][1];
        sleep 3;
        $share_data->[1][1] += 5;
        printf "th %d done , num %d\n", threads->self->tid(), $share_data->[1][1];
}
実行結果
% ./ref3.pl
th 1 start, num 10
th 2 start, num 20
th 1 done , num 25
th 3 start, num 30
th 2 done , num 35
th 3 done , num 40

配列のリファレンス (3次元) をスレッド間で共有

ref4.pl
#!/opt/perl-5.34.1/bin/perl5.34.1
use strict;
use warnings;
use threads;
use threads::shared;

my $share_data = &share([]);

$share_data->[0] = &share([]);
$share_data->[1] = &share([]);

$share_data->[0][0] = 1;
$share_data->[0][1] = &share([]);

$share_data->[0][1][0] = 1;

my $thread_a = threads->create(\&sub_a , 10); sleep 2;
my $thread_b = threads->create(\&sub_a , 20); sleep 2;
my $thread_c = threads->create(\&sub_a , 30); sleep 2;

$thread_a->join();
$thread_b->join();
$thread_c->join();

sub sub_a {
        $share_data->[0][1][1] = shift ;
        printf "th %d start, num %d\n", threads->self->tid(), $share_data->[0][1][1];
        sleep 3;
        $share_data->[0][1][1] += 5;
        printf "th %d done , num %d\n", threads->self->tid(), $share_data->[0][1][1];
}
実行結果
% ./ref4.pl
th 1 start, num 10
th 2 start, num 20
th 1 done , num 25
th 3 start, num 30
th 2 done , num 35
th 3 done , num 40

階層ごとに $array = &share([]); とか %hash = &share({}); していくと多層の共有できる変数が作れる。
でも、 $var->[n] = [ [a,b], [c,d] ] というように、複数の値を一度に扱うことはできない。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?