Разблокирована, безопасность работы с общим хэшем в многопоточном Perl - PullRequest
3 голосов
/ 10 августа 2010

Вопрос

Безопасно ли нескольким потокам извлекать и хранить простые отдельные значения в общем хэше без 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';
}

Ответы [ 3 ]

2 голосов
/ 10 августа 2010

Насколько я понимаю, любая блокировка, необходимая для предотвращения повреждения внутренней структуры хэша, обрабатывается автоматически.Функция lock позволяет координировать потоки, чтобы можно было поддерживать согласованность хэша на более высоком уровне.Поскольку в этом случае каждый ключ изменяется только одним потоком, явной блокировки не требуется.

Я не могу процитировать полномочия, за исключением того, что я не могу найти ничего в threads :: shared документация, которая предполагает, что вы должны быть осторожны, чтобы заблокировать переменную перед ее изменением.Если это может привести к сбою Perl, вы можете подумать, что это стоит упомянуть.

1 голос
/ 06 января 2011

Вот авторитетный ответ. От perlthrtut , в конце «Общие и неразделенные данные»,

Обратите внимание, что общая переменная гарантирует что если два или более потоков пытаются изменить его в то же время, внутреннее состояние переменной воли не стать испорченным Тем не менее, есть кроме этого нет никаких гарантий, так как объяснено в следующем разделе.

Итак, да, безопасно хранить и извлекать простые индивидуальные значения в хэше без блокировки.

1 голос
/ 10 августа 2010

ИМХО, все будет работать нормально.

документы по потокам просто упомяните, что не следует использовать потоки в блоках END, и вообще не упоминайте о мьютексах, кроме этогоЕсли бы мьютексы были необходимы, они наверняка были бы включены в модуль потоков - но это не так?

my %hash : shared;

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

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

print Dumper \%hash;

Каждый раз, когда я запускаю это значение get 300 в каждом ключе.До сих пор я не мог найти лучший способ доказать, что это безопасно.

...