Литмир - Электронная Библиотека
A
A

return $random; # возвращает его

}

Сообщения, выводимые при выполнении этой программы, подтверждают независимое выполнение нитей и основной программы:

Создана 0-я нить. TID=1

Создана 1-я нить. TID=2

1-я нить ждет 7 сек.

0-я нить ждет 1 сек.

Создана 2-я нить. TID=3

2-я нить ждет 3 сек.

2-я нить вернула 3

1-я нить вернула 7

0-я нить вернула 1

Параллельно выполняющийся поток можно "отсоединить", игнорируя его значение: это делается методом $thread->detach, после выполнения которого присоединить нить будет невозможно.

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

use threads; # подключить многопоточные средства

use threads::shared; # и средства разделения данных

my $public : shared = 0; # разделяемая переменная

my $private = 0; # неразделяемая переменная

threads->new(sub { # нить из анонимной подпрограммы

$public++; $private++; # изменяем значения

print "$public $private\n"; # будет выведено: 1 1

})->join; # дожидаемся результатов выполнения:

print "$public ", # 1 ($public изменена в нити)

"$private\n"; # 0 (в нити изменена копия $private)

Чтобы предотвратить в одной нити изменение другими нитями значения разделяемой переменной, эту переменную нужно заблокировать при помощи функции lock(). Разблокирование переменной происходит не с помощью функции, а при выходе из блока, в котором она была заблокирована. Это делается таким образом:

{ # блок для работы с разделяемой переменной

lock $variable; # заблокировать переменную

$variable = $new_value; # и изменить ее значение

} # здесь $variable автоматически разблокируется

Нити могут обмениваться между собой данными. Например, с помощью стандартного модуля Thread::Queue организуется очередь для синхронизированной передачи данных из одной нити в другую. Пользоваться такой очередью гораздо проще, чем рассмотренными ранее программными каналами. Небольшой пример показывает, как помещать скалярные величины в очередь методом enqueue() и извлекать из нее методом dequeue(). Метод pending() возвращает число оставшихся в очереди элементов, поэтому может использоваться для окончания цикла чтения из очереди:

use threads; # подключить средства

use Thread::Queue; # и модуль работы с очередью

my $data_queue = Thread::Queue->new; # создаем очередь

my $thread = threads->new(\&reader); # и нить

# помещаем в очередь скалярные данные:

$data_queue->enqueue(1987); # число

$data_queue->enqueue('год'); # строку

$data_queue->enqueue('рождения', 'Perl'); # список

$thread->join; # ожидаем окончания нити

exit; # перед завершением программы

sub reader { # извлекаем данные из очереди,

while ($data_queue->pending) { # пока она не пуста

my $data_element = $data_queue->dequeue;

print "'$data_element' извлечен из очереди\n";

}

}

Автоматическая синхронизация доступа к очереди гарантирует очередность записи в очередь и чтение из нее, что видно из выполнения этого примера:

'1987' извлечен из очереди

'год' извлечен из очереди

'рождения' извлечен из очереди

'Perl' извлечен из очереди

Конечно, имеющиеся в Perl средства работы с легковесными процессами не ограничиваются перечисленными выше. Стандартные модули предоставляют и другие возможности эффективно организовать различные алгоритмы многопоточной обработки, не говоря уже о дополнительных модулях, имеющихся в архивах CPAN.

Существует много ситуаций, когда применение многозадачности не только оправданно, но и является единственно правильным решением задачи. Поэтому знание средств управления процессами дает вам новую точку зрения на решаемую проблему и расширяет ваш арсенал программных инструментов. В 6-й версии языка Perl средства распределенного программирования будут улучшены и дополнены, появятся сопрограммы (co-routines) и другие интересные возможности.

Лекция 17. Работа в IP-сетях

В этой лекции рассказывается об имеющихся в Perl возможностях обработки данных в IP-сетях, начиная с низкоуровневых средств и заканчивая классами для работы с основными сетевыми протоколами.

Цель лекции: узнать основные механизмы передачи данных по сети и научиться применять их для обработки данных в своих программах, используя стандартные и дополнительные модули Perl.

Сегодня большинство пользователей компьютеров воспринимают возможность обмена данными по компьютерной сети как нечто само собой разумеющееся. Это может быть небольшая офисная сеть из нескольких станций, корпоративная сеть, объединяющая многие сотни компьютеров, или подключение к глобальной сети Интернет. Легкость и удобство работы с многочисленными сетевыми сервисами стала возможной благодаря длительным усилиям многих выдающихся программистов, самых разных компаний и организаций из многих стран мира по созданию существующей инфраструктуры сетевых технологий. Эта инфраструктура основана на огромном числе стандартов, позволяющих согласованно использовать линии связи, аппаратуру передачи данных, компьютеры, операционные системы и прикладные программы для обмена информацией по сети.

71
{"b":"569217","o":1}