スレッド間でデータの共有が必要と言うことで試してみた。
普通の変数をスレッド間で共有
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] ] というように、複数の値を一度に扱うことはできない。