【问题标题】:Sharing a thread variable without making it global (Perl)共享线程变量而不使其成为全局变量 (Perl)
【发布时间】:2016-01-06 08:39:45
【问题描述】:

我正在尝试编写一个使用线程并共享一个变量的简单脚本,但我不想让这个变量对整个脚本都是全局的。下面是一个简化的例子。

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";
    }
}

输出:

用线程 1 做某事! 东西是 1

用线程 2 做一些事情! 某事是 2

用线程 3 做一些事情! 东西是 3

用线程 4 做一些事情! 东西是 4

用线程 5 做某事! 某事是 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);
}

否则我会得到:

全局符号“$val”需要显式封装

什么是词法范围共享变量的正确方法?

【问题讨论】:

  • 除非你传入它,否则一个线程怎么可能既是共享的(全局的)又不是全局的?您似乎想要做的是为您的范围创建一个图层。你也试过使用our($val);吗?
  • 旁注,map { $_->join(); } threads->list(); => $_->join() for threads->list(); 保持你的意图清晰。
  • @Сухой27,谢谢,这更清楚了。
  • @vol7ron,使用our 定义$val 将使其更加全球化。我只希望共享变量只能由线程访问,其他任何地方都无法访问。
  • 它将它暴露给包,但也许这就是你想要的。我有点全神贯注,所以我不应该发表评论,但这可能属于“你尝试了什么?”类别

标签: multithreading perl scope lexical-scope


【解决方案1】:

将引用作为参数传递。

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); };
   }
}

或者限定它,以便只有工作人员可以看到它。

{
   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); };
}

【讨论】:

    【解决方案2】:

    你可以限制共享变量的范围(确保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);
    }
    
    # ...
    

    【讨论】:

      猜你喜欢
      • 2021-08-14
      • 1970-01-01
      • 2017-08-19
      • 1970-01-01
      • 2013-03-22
      • 1970-01-01
      • 1970-01-01
      • 2019-01-15
      • 1970-01-01
      相关资源
      最近更新 更多