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

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

```perl: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;
}
```

```tcsh:実行結果
% ./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 になってますね。
なるほど、ちゃんと変数の値が共有できてます。


# 配列のスレッド間共有

```perl: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];
}
```
実行!
```tcsh:実行結果
% ./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
```
これも共有できてる。

# 配列のリファレンスをスレッド間で共有
マニュアルにあるので、若干不思議な宣言方法ですけども

```perl: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];
}
```

```tcsh:実行結果
% ./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次元) をスレッド間で共有
```perl: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];
}
```

実行結果
```tcsh:実行結果
% ./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次元) をスレッド間で共有 その２
```perl: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];
}
```

```tcsh:実行結果
% ./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次元) をスレッド間で共有
```perl: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];
}
```

```tcsh:実行結果
% ./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] ] というように、複数の値を一度に扱うことはできない。