【问题标题】:Unlocked, shared hash operation safety in threaded perl线程化 perl 中的解锁、共享哈希操作安全
【发布时间】:2011-01-07 04:32:21
【问题描述】:

问题

多个线程在 shared 散列中获取和存储简单的单个值是否安全,而无需 lock() 处理散列?

你能证明它或引用强大的权威吗?

背景

我的信念是,在最坏的情况下,未锁定的哈希操作可能会导致段错误。

但是,我最近看到了以作者认为安全的方式协调工作线程活动的代码。有问题的代码只执行简单的获取和存储:

  • 共享哈希是普通的共享哈希(不是用户定义的 tie()d 构造)
  • 这些值是简单的标量,不是引用,也不是共享的
  • 每个键/值对由一个且只有一个线程唯一存储和修改
  • 任何线程都可以获取所有键/值对
  • 没有线程遍历共享哈希(没有each()、没有keys() 也没有values() 循环)

代码摘录

my %status : shared;

for my $id (1 .. $n) {
  threads->create(\&thread_routine);
}

sub thread_routine {
  my $me = threads->tid();

  $status{ $me } = 'Getting ready';
  ... do something ...
  $status{ $me } = 'Thinking';
  ... do something else ...

  $status{ $me } = 'Looking around';
  for my $tid (threads->list) {
    next if $tid == $me;
    if ($status{ $tid } eq "Thinking") { ... react ... }
    ...
  }

  $status{ $me } = 'All done';
}

【问题讨论】:

  • 最后一行的$key不应该是$me吗?
  • @cjm,没错。已更新。

标签: multithreading perl race-condition


【解决方案1】:

这是一个权威的答案。来自perlthrtut,在“共享和非共享数据”的末尾,

请注意,共享变量保证 如果两个或更多线程尝试 同时修改, 变量的内部状态将 不会被破坏。然而,有 除此之外没有任何保证,因为 在下一节中解释。

所以,是的,在哈希中存储和获取简单的单个值是安全的,无需锁定。

【讨论】:

    【解决方案2】:

    据我了解,为防止哈希内部结构损坏所必需的任何锁定都是自动处理的。 lock 函数是为了让线程进行协调,以便保持哈希的更高级别的一致性。由于在这种情况下每个键只被一个线程修改,因此不需要显式锁定。

    我不能引用权威,除了我在threads::shared 文档中找不到任何建议您在修改变量之前需要小心锁定变量的内容。如果这样做会导致 Perl 崩溃,您会认为这值得一提。

    【讨论】:

      【解决方案3】:

      恕我直言,它会正常工作的。

      threads module docs 只是提到不要在 END 块中使用线程,并且在其他任何地方都不要提及互斥锁。如果需要互斥锁,它们肯定会包含在线程模块中 - 但它们不是,是吗?

      my %hash : shared;
      
      map {
              async { map { $hash{$_}++; } (1 .. 30); }
      } (1 .. 300);
      
      map {$_->join} (threads->list);
      
      print Dumper \%hash;
      

      每次我在每个键中运行一个获取值 300。到目前为止,我找不到更好的方法来证明它是安全的。

      【讨论】:

      • Mutex 包含在所有shared 变量中,它们都带有Java 程序员可能称之为“内在”或“监控”锁的东西。
      • 这意味着它会起作用。我还发现threads::shared模块导出了lock方法,允许手动创建锁。
      猜你喜欢
      • 1970-01-01
      • 2011-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-05
      • 1970-01-01
      • 2011-03-14
      相关资源
      最近更新 更多