共享线程变量而不使其成为全局变量 (Perl)
Sharing a thread variable without making it global (Perl)
我正在尝试编写一个使用线程并共享一个变量的简单脚本,但我不想让这个变量成为整个脚本的全局变量。下面是一个简化的例子。
use strict;
use warnings;
use threads;
use threads::shared;
my $val:shared;
# Create threads
for my $i (1 .. 5) {
threads->create(\&do_something, $i);
}
# Wait for all threads to complete
map { $_->join(); } threads->list();
# $val is global to the script so this line will work!
print "VAL IS: $val\n";
sub do_something {
my $i = shift;
print "Doing something with thread $i!\n";
{
lock $val;
$val = "SOMETHING IS $i";
print "$val\n\n";
}
}
输出:
Doing something with thread 1!
SOMETHING IS 1
Doing something with thread 2!
SOMETHING IS 2
Doing something with thread 3!
SOMETHING IS 3
Doing something with thread 4!
SOMETHING IS 4
Doing something with thread 5!
SOMETHING IS 5
VAL IS: SOMETHING IS 5
如何在不让整个脚本访问 $val
的情况下获得这种效果?换句话说,我怎样才能使尝试打印 VAL IS: $val
失败,但变量仍会被线程成功共享?
我不能这样定义它:
# Create threads
for my $i (1 .. 5) {
my $val:shared;
threads->create(\&do_something, $i);
}
或者我会得到:
Global symbol "$val" requires explicit package
共享变量的词法作用域的正确方法是什么?
将对它的引用作为参数传递。
sub do_something {
my ($id, $lock_ref) = @_;
print("$id: Started\n");
{
lock $$lock_ref;
print("$id: Exclusive\n");
sleep(1);
}
print("$id: done.\n");
}
{
my $lock :shared;
for my $id (1..5) {
async { do_something($id, $lock); };
}
}
或者限定它的范围,以便只有 worker sub 可以看到它。
{
my $lock :shared;
sub do_something {
my ($id) = @_;
print("$id: Started\n");
{
lock $lock;
print("$id: Exclusive\n");
sleep(1);
}
print("$id: done.\n");
}
}
for my $id (1..5) {
async { do_something($id); };
}
您可以限制共享变量的范围(确保 perl 在创建线程之前看到共享变量),
# ..
{
my $val:shared;
sub do_something {
my $i = shift;
print "Doing something with thread $i!\n";
{
lock $val;
$val = "SOMETHING IS $i";
print "$val\n\n";
}
}
}
# Create threads
for my $i (1 .. 5) {
threads->create(\&do_something, $i);
}
# ...
我正在尝试编写一个使用线程并共享一个变量的简单脚本,但我不想让这个变量成为整个脚本的全局变量。下面是一个简化的例子。
use strict;
use warnings;
use threads;
use threads::shared;
my $val:shared;
# Create threads
for my $i (1 .. 5) {
threads->create(\&do_something, $i);
}
# Wait for all threads to complete
map { $_->join(); } threads->list();
# $val is global to the script so this line will work!
print "VAL IS: $val\n";
sub do_something {
my $i = shift;
print "Doing something with thread $i!\n";
{
lock $val;
$val = "SOMETHING IS $i";
print "$val\n\n";
}
}
输出:
Doing something with thread 1! SOMETHING IS 1
Doing something with thread 2! SOMETHING IS 2
Doing something with thread 3! SOMETHING IS 3
Doing something with thread 4! SOMETHING IS 4
Doing something with thread 5! SOMETHING IS 5
VAL IS: SOMETHING IS 5
如何在不让整个脚本访问 $val
的情况下获得这种效果?换句话说,我怎样才能使尝试打印 VAL IS: $val
失败,但变量仍会被线程成功共享?
我不能这样定义它:
# Create threads
for my $i (1 .. 5) {
my $val:shared;
threads->create(\&do_something, $i);
}
或者我会得到:
Global symbol "$val" requires explicit package
共享变量的词法作用域的正确方法是什么?
将对它的引用作为参数传递。
sub do_something {
my ($id, $lock_ref) = @_;
print("$id: Started\n");
{
lock $$lock_ref;
print("$id: Exclusive\n");
sleep(1);
}
print("$id: done.\n");
}
{
my $lock :shared;
for my $id (1..5) {
async { do_something($id, $lock); };
}
}
或者限定它的范围,以便只有 worker sub 可以看到它。
{
my $lock :shared;
sub do_something {
my ($id) = @_;
print("$id: Started\n");
{
lock $lock;
print("$id: Exclusive\n");
sleep(1);
}
print("$id: done.\n");
}
}
for my $id (1..5) {
async { do_something($id); };
}
您可以限制共享变量的范围(确保 perl 在创建线程之前看到共享变量),
# ..
{
my $val:shared;
sub do_something {
my $i = shift;
print "Doing something with thread $i!\n";
{
lock $val;
$val = "SOMETHING IS $i";
print "$val\n\n";
}
}
}
# Create threads
for my $i (1 .. 5) {
threads->create(\&do_something, $i);
}
# ...