在线程perl中解锁,共享散列操作安全性

时间:2010-08-10 18:06:49

标签: multithreading perl race-condition

问题

多个线程在没有lock()哈希的shared哈希中获取和存储简单的单个值是否安全?

你能证明它还是引用强大的权威?

背景

我的信念是,最坏的解锁哈希操作可能会导致段错误。

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

  • 共享哈希是一个普通的共享哈希(不是用户定义的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';
}

3 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

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

threads module docs只是提到不要在END块中使用线程,除此之外的任何地方都不要提及互斥锁。如果互斥量是必要的,他们肯定会被包含在线程模块中 - 但它们不是,是吗?

my %hash : shared;

map {
        async { map { $hash{$_}++; } (1 .. 30); }
} (1 .. 300);

map {$_->join} (threads->list);

print Dumper \%hash;

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

答案 2 :(得分:1)

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

  

请注意,共享变量可以保证   如果两个或多个线程试图   同时修改它,   变量的内部状态会   不会变得腐败。但是,那里   除此之外没有任何保证   在下一节中解释。

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