多个线程在没有lock()
哈希的shared哈希中获取和存储简单的单个值是否安全?
你能证明它还是引用强大的权威?
我的信念是,最坏的解锁哈希操作可能会导致段错误。
但是,我最近看到的代码以这种方式协调工作线程的活动,作者认为这是安全的。有问题的代码只执行简单的提取和存储:
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';
}
答案 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,在“共享和非共享数据”的末尾,
请注意,共享变量可以保证 如果两个或多个线程试图 同时修改它, 变量的内部状态会 不会变得腐败。但是,那里 除此之外没有任何保证 在下一节中解释。
所以,是的,在哈希中存储和获取简单的单个值是安全的。