Можно ли создавать общие переменные внутри потока? - PullRequest
1 голос
/ 29 сентября 2010

Я думаю, это может быть довольно простой вопрос.

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

Причина, по которой мне это нужно, в том, что у меня есть общий хеш, который сопоставляет ключи с ссылками на массивы. Эти ссылки создаются / заполняются одним потоком, а считываются / изменяются другим (предполагается правильная синхронизация). Чтобы сохранить эти ссылки на массивы, я должен сделать их общими. В противном случае я получаю ошибку Invalid value for shared scalar.

Ниже приведен пример:

my %hash :shared;

my $t1 = threads->create(
    sub { my @ar :shared = (1,2,3); $hash{foo} = \@ar });
$t1->join;

my $t2 = threads->create(
    sub { print Dumper(\%hash) });
$t2->join;

Это работает, как и ожидалось: второй поток видит изменения, сделанные первым. Но так ли это при любых обстоятельствах?


Некоторые уточнения (относительно ответа Яна):

У меня есть одна нить, читающая из канала и ожидающая ввода. Если они есть, поток A запишет эти входные данные в общий хеш (он отображает скаляры в хэши ... это те хэши, которые также должны быть объявлены общими) и продолжает прослушивать канал. Другой поток B получает уведомление (через cond_wait / cond_signal) о том, что нужно что-то делать, работает над содержимым в общем хэше и удаляет соответствующие записи после завершения. Тем временем А может добавлять новые вещи в хеш.

Так что по вопросу Яна

[...] Следовательно, большинство людей создают все свои общие переменные перед запуском каких-либо подпотоков.

Поэтому, даже если общие переменные могут быть созданы в потоке, насколько это будет полезно?

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

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

Ответы [ 3 ]

3 голосов
/ 29 сентября 2010

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

3 голосов
/ 29 сентября 2010

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

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

Поэтому, даже если в потоке могут быть созданы общие переменные, насколько это будет полезно? (PS, я не знаю, есть ли что-нибудь в perl, которое препятствует созданию общих переменных в потоке.)


PS Хороший дизайн приведет к очень небольшому количеству (если таковые имеются) общих переменных

0 голосов
/ 22 октября 2010

Я не чувствую себя хорошо, отвечая на свой вопрос, но думаю, что ответы до сих пор на него не отвечают. Если что-то получится, я был бы рад принять это. Ответ Эрика помог, хотя.

Теперь я думаю, что нет проблем с разделением переменных внутри потоков. Аргументация: метод Threads::Queue enqueue() разделяет, что он ставит в очередь. Это происходит с shared_clone. Поскольку постановка в очередь должна быть хороша для любого потока, совместное использование должно также выполняться.

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