Разработка Perl-скрипта с многопоточностью и обменом данными между потоками. - PullRequest
0 голосов
/ 11 августа 2010

Я пишу Perl-скрипт для запуска какого-то конвейера.Я начинаю с чтения файла JSON с кучей параметров.Затем я выполняю некоторую работу - в основном создаю некоторые структуры данных, необходимые позже, и вызываю внешние программы, которые генерируют некоторые выходные файлы, на которые я храню ссылки.

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

Эти шаги могут занять хорошую паруминут, если это делается последовательно, но большинство из них можно запустить параллельно с некоторой простой логикой зависимостей, которые я знаю, как обрабатывать (используя потоки и очередь).Поэтому мне интересно, как я должен реализовать это, чтобы позволить обмен данными между потоками.Что бы вы предложили в качестве основы?Возможно, использовать объект (из которого у меня будет только один экземпляр) и хранить все общие данные в $self?Возможно, простой скрипт (без объектов) с некоторыми «глобальными» общими переменными?...

Очевидно, я бы предпочел простое, аккуратное решение.

Ответы [ 2 ]

3 голосов
/ 11 августа 2010

Чтение threads::shared. По умолчанию, как вы знаете, переменные perl не являются общими. Но вы помещаете атрибут shared на них, и они есть.

my %repository: shared;

Тогда, если вы хотите синхронизировать доступ к ним, самый простой способ -

{   lock( %repository );
    $repository{JSON_dump} = $json_dump;
}
# %respository will be unlocked at the end of scope.

Однако вы можете использовать Thread::Queue, которые должны быть свободны от мусса, и сделать это также:

$repo_queue->enqueue( JSON_dump => $json_dump );

Тогда ваш потребительский поток может просто:

my ( $key, $value ) = $repo_queue->dequeue( 2 );
$repository{ $key } = $value;
1 голос
/ 11 августа 2010

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

Что бы я хотелна самом деле предлагаю вам использовать, при условии, что вы можете, вместо этого - систему управления очередью, такую ​​как Gearman , которая имеет различные интерфейсы, включая модуль Perl.Это позволяет вам создать столько «рабочих», сколько вы хотите (подпрограммы фактически выполняют работу) и создать одного простого «клиента», который бы планировал соответствующие задачи и затем сопоставлял результаты, не прибегая к использованию трюков, как при использовании конкретных ключей хеш-реферак задаче или тому подобному.

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

Другие системы очередей, такие как TheSchwartz, не будут указаны, так как им не хватает обратной связи / результата, который обеспечивает Gearman.В любом случае, использование Gearman таким образом во многом похоже на описанную вами многопоточную систему, без лишних хлопот и головной боли, от которой может в конечном итоге пострадать любая система, основанная на потоках: блокировка переменных, использование семафоров, присоединение к потокам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...