很常见的是,解决一些问题的关键是选择一个好的表示。如果您以表格形式表示您的问题:
T1 => { locked => [ qw( X1 X2 X3 ) ], waiting => [ qw( X4 X5 X6 X7 ) ] },
T2 => { locked => [ qw( X4 X5 X6 ) ], waiting => [ qw( X7 X8 X9 ) ] },
T3 => { locked => [ qw( X7 X8 ) ], waiting => [ qw( X1 X10 X111 ) ] },
T4 => { locked => [ qw( X9 X10 ) ], waiting => [ qw( X7 X11 X12 ) ] },
T5 => { locked => [ qw( X11 X12 ) ], waiting => [ qw( X5 ) ] },
T6 => { locked => [ qw( X13 X14 ) ], waiting => [ qw( X6 X1 X2 X3 X11 X12 ) ] },
T7 => { locked => [ qw( X15 ) ], waiting => [ qw( X5 ) ] },
T8 => { locked => [ qw( X1111 ) ], waiting => [ qw( X1 X115 ) ] },
T9 => { locked => [ qw( X115 ) ], waiting => [ qw( X1 ) ] },
T10 => { locked => [ qw( X199 ) ], waiting => [ qw( X11 X12 ) ] },
然后你可以更有效地推理手头的问题。很容易看到某个事务正在等待什么资源,从那里你可以看到哪些事务持有这些资源。递归地应用该推理。如果你最终进入一个循环,你刚刚发现了一个死锁。
'当然,表示甚至可以更好:
use strict;
use warnings;
use Data::Dumper;
my %transactions = (
T1 => { locked => [ qw( X1 X2 X3 ) ], waiting => [ qw( X4 X5 X6 X7 ) ] },
T2 => { locked => [ qw( X4 X5 X6 ) ], waiting => [ qw( X7 X8 X9 ) ] },
T3 => { locked => [ qw( X7 X8 ) ], waiting => [ qw( X1 X10 X111 ) ] },
T4 => { locked => [ qw( X9 X10 ) ], waiting => [ qw( X7 X11 X12 ) ] },
T5 => { locked => [ qw( X11 X12 ) ], waiting => [ qw( X5 ) ] },
T6 => { locked => [ qw( X13 X14 ) ], waiting => [ qw( X6 X1 X2 X3 X11 X12 ) ] },
T7 => { locked => [ qw( X15 ) ], waiting => [ qw( X5 ) ] },
T8 => { locked => [ qw( X1111 ) ], waiting => [ qw( X1 X115 ) ] },
T9 => { locked => [ qw( X115 ) ], waiting => [ qw( X1 ) ] },
T10 => { locked => [ qw( X199 ) ], waiting => [ qw( X11 X12 ) ] },
);
# get a data-item -> transaction mapping
my %items;
for my $transaction (keys %transactions) {
for my $item (@{$transactions{$transaction}->{locked}}) {
$items{$item} = $transaction;
}
}
my @nodes;
my @edges;
for my $transaction (keys %transactions) {
push @nodes, $transaction;
for my $item (@{$transactions{$transaction}->{waiting}}) {
push @edges, { source => $transaction, dest => $items{$item}, item => $item } if $items{$item};
}
}
print "digraph tx_dependencies {\n";
print " $_ label=$_;\n" for @nodes;
print " @{[ $_->{source} ]} -> @{[ $_->{dest} ]} [label=@{[ $_->{item} ]}];\n" for @edges;
print "}\n";
该程序会生成一个 graphviz 文件,当对其进行适当的按摩时,dot
最终结果为: