LINUX.ORG.RU

[Perl][Threads] Как попасть в deadlock?

 


0

1

Пытаюсь организовать deadlock из познавательного интереса. Вот немного улучшенный пример из perlthtut (http://perldoc.perl.org/perlthrtut.html#A-Thread-Pitfall:-Deadlocks):

#!/usr/bin/perl
use threads;
use feature 'say';

my $a :shared = 4;
my $b :shared = 'foo';

my $thr1 = threads->create(sub {
	{
		lock $a  &&  say "thr1: \$a locked";
		sleep 3;
		lock $b  &&  say "thr1: \$b locked";
	}
	say "thr1: \$a unlocked";
	say "thr1: \$b unlocked";
});

sleep 1;

my $thr2 = threads->create(sub {
	{
		lock $b  &&  say "thr2: \$b locked";
		lock $a  &&  say "thr2: \$a locked";
	}
	say "thr2: \$a unlocked";
	say "thr2: \$b unlocked";

});

$thr1->join();
$thr2->join();

Казалось бы, гарантированный deadlock и обе нити должны замереть на вечность в ожидании блокировки. Но не тут-то было. Не виснет вообще ни разу! :/

При запуске получаем:

thr1: $a locked
thr2: $b locked
thr2: $a locked
thr2: $a unlocked
thr2: $b unlocked
thr1: $b locked
thr1: $a unlocked
thr1: $b unlocked

То есть, $thr2 получает блок на $a, хотя она в это время заблокирована из $thr1.
Как так? :)

P.S.

shovel@r2d2> perl -v | head -2

This is perl 5, version 12, subversion 4 (v5.12.4) built for i486-linux-gnu-thread-multi-64int
OC: Debian testing



Последнее исправление: visla_vi (всего исправлений: 1)

У тебя первый тред лочит ресурсы и потом завершается, ресурсы походу освобождаются при выходе из скоупа.

# мб, я и глючу

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от kim-roader

Да, вот так отлично работает. Виснет 100% :)

То есть, без

use threads;
use threads::shared;
артибут :shared ничего не даёт. Что, в общем, естественно))). А значит, переменные $a и $b остаются локальными для каждого потока.

visla_vi
() автор топика
Ответ на: комментарий от DELIRIUM

Всё правильно, это особенность lock() в Perl, при выходе из блока кода автоматически происходит unlock() всех его lock'ов.

Тред $thr1 лочит $a; замирает на 3 секунды
В то время, пока $thr1 замер, тред $thr2 лочит $b и начинает ожидать разблокировки $a (она заблокирована в $thr1)
sleep в $thr1 завершается, и он пытается заблокировать $b. А она уже заблокирована в $thr2.

Теперь $thr2 имеет $a и ждёт $b
А $thr1 имеет $b и ждёт $a

классический такой deadlock :)

visla_vi
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.