很常见的是,解决一些问题的关键是选择一个好的表示。如果您以表格形式表示您的问题:
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
最终结果为:
![有向图 tx_dependencies {T1 标签=T1;T9 标签=T9;T8 标签=T8;T3 标签=T3;T4 标签=T4;T6 标签=T6;T7 标签=T7;T5 标签=T5;T10 标签=T10;T2 标签=T2;T1 -> T2 [标签=X4];T1 -> T2 [标签=X5];T1 -> T2 [标签=X6];T1 -> T3 [标签=X7];T9 -> T1 [标签= X1];T8 -> T1 [标签=X1];T8 -> T9 [标签=X115];T3 -> T1 [标签=X1];T3 -> T4 [标签=X10];T4 -> T3 [标签= X7];T4 -> T5 [标签=X11];T4 -> T5 [标签=X12];T6 -> T2 [标签=X6];T6 -> T1 [标签=X1];T6 -> T1 [标签= X2];T6 -> T1 [标签=X3];T6 -> T5 [标签=X11];T6 -> T5 [标签=X12];T7 -> T2 [标签=X5];T5 -> T2 [标签= X5];T10 -> T5 [标签=X11];T10 -> T5 [标签=X12];T2 -> T3 [标签=X7];T2 -> T3 [标签=X8];T2 -> T4 [标签= X9];}](https://i.stack.imgur.com/hrquV.png)