Чтение онлайн

на главную

Жанры

Язык программирования Perl

Шохирев Михаил Васильевич

Шрифт:

@result = $thread->join;

Действие, выполняемое методом join, называется "присоединение нити" или "объединение потоков". Как это происходит, показано на рис. 16.2.

Рис. 16.2.Присоединение нити с помощью join

Каждой нити присваивается числовой идентификатор (Thread Identifier, TID), который можно получить с помощью метода tid.

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

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

my @thread = ; # массив объектов типа threads

for (my $i = 0; $i <= 2; $i++) { # создаем 3 нити

$thread[$i] = threads->new(\&pearl_thread, $i);

print "Создана $i-я нить. TID=", $thread[$i]->tid, "\n";

}

for (my $i = 2; $i >= 0; $i--) { # присоединяем нити

print "$i-я нить вернула ", $thread[$i]->join, "\n";

}

sub pearl_thread ($) { # нить получает

my $number = shift; # число, генерирует

my $random = int(rand(7)) + 1; # случайное значение,

print "\t$number-я нить ждет $random сек.\n";

sleep $random; # и, подождав немного,

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";

}

}

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

Поделиться:
Популярные книги

Кодекс Крови. Книга Х

Борзых М.
10. РОС: Кодекс Крови
Фантастика:
фэнтези
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга Х

Легат

Прокофьев Роман Юрьевич
6. Стеллар
Фантастика:
боевая фантастика
рпг
6.73
рейтинг книги
Легат

Защитник. Второй пояс

Игнатов Михаил Павлович
10. Путь
Фантастика:
фэнтези
5.25
рейтинг книги
Защитник. Второй пояс

Счастье быть нужным

Арниева Юлия
Любовные романы:
любовно-фантастические романы
5.25
рейтинг книги
Счастье быть нужным

Огненный князь 3

Машуков Тимур
3. Багряный восход
Фантастика:
фэнтези
боевая фантастика
попаданцы
5.00
рейтинг книги
Огненный князь 3

Гром над Академией Часть 3

Машуков Тимур
4. Гром над миром
Фантастика:
фэнтези
5.25
рейтинг книги
Гром над Академией Часть 3

Не грози Дубровскому! Том III

Панарин Антон
3. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Не грози Дубровскому! Том III

Не отпускаю

Шагаева Наталья
Любовные романы:
современные любовные романы
эро литература
8.44
рейтинг книги
Не отпускаю

Флеш Рояль

Тоцка Тала
Детективы:
триллеры
7.11
рейтинг книги
Флеш Рояль

Приручитель женщин-монстров. Том 4

Дорничев Дмитрий
4. Покемоны? Какие покемоны?
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Приручитель женщин-монстров. Том 4

Кодекс Охотника. Книга XVIII

Винокуров Юрий
18. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XVIII

Польская партия

Ланцов Михаил Алексеевич
3. Фрунзе
Фантастика:
попаданцы
альтернативная история
5.25
рейтинг книги
Польская партия

Курсант: Назад в СССР 7

Дамиров Рафаэль
7. Курсант
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Курсант: Назад в СССР 7

Белые погоны

Лисина Александра
3. Гибрид
Фантастика:
фэнтези
попаданцы
технофэнтези
аниме
5.00
рейтинг книги
Белые погоны