U.S. patent application number 11/315855 was filed with the patent office on 2007-06-28 for methods and apparatus for detecting deadlock in multithreading programs.
This patent application is currently assigned to International Business Machines Corporation. Invention is credited to George B. JR. Leeman.
Application Number | 20070150897 11/315855 |
Document ID | / |
Family ID | 38184601 |
Filed Date | 2007-06-28 |
United States Patent
Application |
20070150897 |
Kind Code |
A1 |
Leeman; George B. JR. |
June 28, 2007 |
Methods and apparatus for detecting deadlock in multithreading
programs
Abstract
A method of detecting deadlock in a multithreading program is
provided. An invocation graph is constructed having a single root
and a plurality of nodes corresponding to one or more functions
written in code of the multithreading program. A resource graph is
computed in accordance with one or more resource sets in effect at
each node of the invocation graph. It is determined whether cycles
exist between two or more nodes of the resource graph. A cycle is
an indication of deadlock in the multithreading program.
Inventors: |
Leeman; George B. JR.;
(Ridgefield, CT) |
Correspondence
Address: |
Ryan, Mason & Lewis, LLP
90 Forest Avenue
Locust Valley
NY
11560
US
|
Assignee: |
International Business Machines
Corporation
Armonk
NY
|
Family ID: |
38184601 |
Appl. No.: |
11/315855 |
Filed: |
December 22, 2005 |
Current U.S.
Class: |
718/104 |
Current CPC
Class: |
G06F 9/524 20130101 |
Class at
Publication: |
718/104 |
International
Class: |
G06F 9/46 20060101
G06F009/46 |
Claims
1. A method of detecting deadlock in a multithreading program,
comprising the steps of: constructing an invocation graph having a
single root and a plurality of nodes corresponding to one or more
functions written in code of the multithreading program; computing
a resource graph in accordance with one or more resource sets in
effect at each node of the invocation graph; and determining
whether cycles exist between two or more nodes of the resource
graph, wherein a cycle is an indication of deadlock in the
multithreading program.
2. The method of claim 1, wherein the multithreading program
comprises a Java.TM. program.
3. The method of claim 1, wherein, in the step of constructing an
invocation graph, each node comprises basic blocks of a control
flow graph of a function written in the code of the multithreading
program and locations where resources are accessed and
released.
4. The method of claim 1, wherein, in the step of constructing an
invocation graph, each edge connecting two nodes corresponds to an
invocation of a function written in the code of the multithreading
program from within another function written in the code of the
multithreading program.
5. The method of claim 1, wherein, in the step of constructing an
invocation graph, the invocation graph allows for bidirectional
traversal between nodes to determine sets of predecessor nodes and
successor nodes.
6. The method of claim 1, wherein the step of constructing an
invocation graph comprises the step of performing a data flow
analysis.
7. The method of claim 1, wherein, in the step of constructing an
invocation graph, each node in the invocation graph is identifiable
by a calling context.
8. The method of claim 7, wherein the calling context comprises at
least one of a target function, a set of possible receiver types,
and parameter types.
9. The method of claim 1, wherein, in the step of computing a
resource graph, a resource comprises an object and a counter, and a
resource set comprises resources having distinct objects.
10. The method of claim 1, wherein the step of computing a resource
graph comprises the steps of: constructing a set of nodes and edges
in accordance with the resource sets in effect at each node of the
invocation graph; and refining a definition of the resource graph
through post-processing.
11. The method of claim 10, wherein the step of constructing a set
of nodes and edges comprises the steps of: calculating a first
resource set from the invocation graph; adding edges as resources
are requested; computing resource sets for each edge leaving a node
of the first resource set; updating the resource graph as required
after each step; and repeating the calculating, adding, computing
and updating steps for each newly created resource set.
12. The method of claim 10, wherein the step of refining a
definition of the lock graph comprises the step of examining a
current set of vertices to generate additional edges.
13. The method of claim 1, further comprising the step of reporting
any cycles with associated path information.
14. Apparatus for detecting deadlock in a multithreading program,
comprising: a memory; and at least one processor coupled to the
memory and operative to: (i) construct an invocation graph having a
single root and a plurality of nodes corresponding to one or more
functions written in code of the multithreading program; (ii)
compute a resource graph in accordance with one or more resource
sets in effect at each node of the invocation graph; and (iii)
determine whether cycles exist between two or more nodes of the
resource graph, wherein a cycle is an indication of deadlock in the
multithreading program.
15. The apparatus of claim 14, wherein the multithreading program
comprises a Java.TM. program.
16. The apparatus of claim 14, wherein, in the operation of
constructing an invocation graph, each node comprises basic blocks
of a control flow graph of a function written in the code of the
multithreading program and locations where resources are accessed
and released.
17. The apparatus of claim 14, wherein, in the operation of
constructing an invocation graph, each edge connecting two nodes
corresponds to an invocation of a function written in the code of
the multithreading program from within another function written in
the code of the multithreading program.
18. The apparatus of claim 14, wherein, in the operation of
constructing an invocation graph, the invocation graph allows for
bidirectional traversal between nodes to determine sets of
predecessor nodes and successor nodes.
19. The apparatus of claim 14, wherein the operation of
constructing an invocation graph comprises the step of performing a
data flow analysis.
20. The apparatus of claim 14, wherein, in the operation of
constructing an invocation graph, each node in the invocation graph
is identifiable by a calling context.
21. The apparatus of claim 20, wherein the calling context
comprises at least one of a target function, a set of possible
receiver types, and parameter types.
22. The apparatus of claim 14, wherein, in the operation of
computing a resource graph, a resource comprises an object and a
counter, and a resource set comprises resources having distinct
objects.
23. The apparatus of claim 14, wherein the operation of computing a
resource graph comprises the steps of: constructing a set of nodes
and edges in accordance with the resource sets in effect at each
node of the invocation graph; and refining a definition of the
resource graph through post-processing.
24. The apparatus of claim 23, wherein the step of constructing a
set of nodes and edges comprises the steps of: calculating a first
resource set from the invocation graph; adding edges as resources
are requested; computing resource sets for each edge leaving a node
of the first resource set; updating the resource graph as required
after each step; and repeating the calculating, adding, computing
and updating steps for each newly created resource set.
25. The apparatus of claim 24, wherein the step of refining a
definition of the lock graph comprises the step of examining a
current set of vertices to generate additional edges.
26. The apparatus of claim 14, further comprising the operation of
reporting any cycles with associated path information.
27. An article of manufacture for detecting deadlock in a
multithreading program, comprising a machine readable medium
containing one or more programs which when executed implement the
steps of: constructing an invocation graph having a single root and
a plurality of nodes corresponding to one or more functions written
in code of the multithreading program; computing a resource graph
in accordance with one or more resource sets in effect at each node
of the invocation graph; and determining whether cycles exist
between two or more nodes of the resource graph, wherein a cycle is
an indication of deadlock in the multithreading program.
Description
FIELD OF THE INVENTION
[0001] The present invention relates generally to multithreading
programs and, more particularly, to techniques for detecting
deadlock in multithreading programs.
BACKGROUND OF THE INVENTION
[0002] Deadlock is a pernicious condition in which multiple
processes are prohibited from making progress, because each is
waiting for one or more resources that are being used by some other
process. However, deadlock is difficult to detect because it may
occur only under specific conditions involving, for example, the
interleaving or timing of the executing threads.
[0003] In a simple example of deadlock, an operating system
contains two files, file1 and file2. Two concurrently running
processes, thread1 and thread2, both require file1 and file2 to
complete successfully. If thread1 opens file1, and thread2 opens
file2, deadlock may result when thread1 attempts to open file2
before closing file1, and thread2 attempts to open file1 before
closing file2. Thus, the two processes could wait forever.
[0004] Several authors have provided characterizations of deadlock
through the application of fundamental assumptions regarding
concurrently running threads that require various resources, see,
for example, W. W. Collier, "System Deadlocks," Tech. Rep.
TR-00.1756, IBM Systems Development Division, New York, 1968; J. W.
Havender, "Avoiding Deadlock in Multitasking Systems," IBM Syst. J.
7, 2 (1968), pp. 74-84; J. E. Murphy, "Resource Allocation with
Interlock Detection in a Multi-Task System," In Proc. FJCC, AFIPS
(1968), vol. 33; and A. Shoshani et al., "Prevention, Detection,
and Recovery from System Deadlocks," In Proceedings of the Fourth
Annual Princeton Conference on Information Sciences and Systems
(March 1970).
[0005] Three such fundamental assumptions that may be made about
concurrently running threads include:
[0006] 1) Mutual exclusion--threads claim exclusive control of the
resources they require;
[0007] 2) Wait for--threads hold resources already allocated to
them, and must await additional required resources; and
[0008] 3) No preemption--resources cannot be forcibly removed from
the threads holding them until the resources are used to
completion.
[0009] In the context of the Java.TM. language (Sun Microsystems,
Inc.), the three fundamental assumptions described above are
satisfied and the resources of interest are locks.
[0010] When these fundamental assumptions hold, deadlock may be
characterized by a resource graph, see, for example W. W. Collier;
J. W. Havender; J. E. Murphy; and A. Shoshani et al. A graph is
defined as a pair (N, E), where N is a set of nodes and E is a set
of edges. If there are n distinct resources, the graph has n nodes,
with each node representing a single resource. Each edge is of the
form (v, w), where v .epsilon. N and w .epsilon. N. Edge (v,w)
extends from node v to node w if there exists a thread with an
execution path that acquires resource v and subsequently requests
resource w. A path in a graph is a set {(v.sub.i,v.sub.i+1)|i=1, .
. . n} of edges, where n.gtoreq.1. A cycle is a path in which
v.sub.1, . . . ,v.sub.n are all distinct, and
v.sub.n+1=v.sub.1.
[0011] Assuming that a thread does not request a resource it has
already acquired, if deadlock occurs, then the resource graph
contains at least one cycle. In the context of programming
languages, such as Java.TM., the use of the graph may be termed a
lock cycle strategy, because of the search for cycles of lock
acquisitions and requests.
[0012] Therefore it would be desirable to automatically determine
whether deadlock will occur through source and object code of a
multithreading program without having to execute the code of the
multithreading program.
SUMMARY OF THE INVENTION
[0013] In multithreading languages such as Java.TM., deadlock is a
serious condition that should be avoided for proper program
functioning. The embodiments of the present invention that detect
deadlock in Java.TM. byte code are automatic and do not require any
annotation of the byte code. The presence of deadlock is reported
precisely, and a user may examine the output to determine if the
code needs to be modified. Thus, static analysis techniques may be
utilized in accordance with the embodiments of the present
invention.
[0014] For example, in one aspect of the present invention, a
method of detecting deadlock in a multithreading program is
provided. An invocation graph is constructed having a single root
and a plurality of nodes corresponding to one or more functions
written in code of the multithreading program. A resource graph is
computed in accordance with one or more resource sets in effect at
each node of the invocation graph. It is determined whether cycles
exist between two or more nodes of the resource graph. A cycle is
an indication of deadlock in the multithreading program.
[0015] Additionally, the resource graph may be constructed through
the construction of a set of nodes and edges in accordance with the
resource sets in effect at each node of the invocation graph. A
definition of the resource graph may be refined through
post-processing to generate additional edges. Finally, any cycles
may be reported to a user with associated path information.
[0016] The approach of the present invention includes detailed
reporting at both the interprocedural and intraprocedural level
allowing for the clear identification of resource contention
locations. The method is general in that it works on a resource
cycle strategy through an abstract description of the program
involving graphs and not details of the programming language. Thus,
the embodiments of the present invention may be applied to any
language which implements monitors and may be scaled to large
problems.
[0017] These and other objects, features and advantages of the
present invention will become apparent from the following detailed
description of illustrative embodiments thereof, which is to be
read in connection with the accompanying drawings.
BRIEF DESCRIPTION OF THE DRAWINGS
[0018] FIG. 1 is a flow diagram illustrating a deadlock detection
methodology, according to an embodiment of the present
invention;
[0019] FIG. 2 is a flow diagram illustrating lock graph computation
methodology, according to an embodiment of the present
invention;
[0020] FIG. 3 is a lock set construction methodology, according to
an embodiment of the present invention;
[0021] FIG. 4 is Java.TM. code for an example used to illustrate an
embodiment of the present invention;
[0022] FIG. 5 is a table of indices, program counters and source
line numbers for the example used to illustrate an embodiment of
the present invention;
[0023] FIG. 6 is a portion of an invocation graph for the example
used to illustrate an embodiment of the present invention;
[0024] FIG. 7 is lock graph for the example used to illustrate an
embodiment of the present invention;
[0025] FIG. 8 is output produced for the example used to illustrate
an embodiment of the present invention; and
[0026] FIG. 9 is a block diagram illustrating an exemplary hardware
implementation of a computing system in accordance with which one
or more components/methodologies of the invention may be
implemented, according to an embodiment of the present
invention.
DETAILED DESCRIPTION OF PREFERRED EMBODIMENTS
[0027] As will be illustrated in detail below, the present
invention introduces techniques for detecting deadlock in
multithreading programs. The embodiments of the present invention
may be implemented for any multithreading program implementing
monitors, however, for illustrative purposes they are described
herein as applied to a Java.TM. program.
[0028] The embodiments of the present invention may be utilized for
both source code and byte code. In the former case, the source code
is compiled and the approach is applied to Java.TM. archive (jar)
files containing the byte code. In the latter case, the methodology
may be applied even if the source code is unavailable, which may
frequently occur. The embodiments are automatic, and no annotation
of the code is required. The jar files are input to the system
along with some configuration data, and the output is a report that
includes a summary of potential deadlocks.
[0029] The Java.TM. language makes use of monitors, which protect a
body of code by ensuring that it can be executed only a single
thread at a time. This is achieved through the use of a lock that
is implicitly associated with each Java.TM. object. Thus, as
described above and in accordance with the embodiments of the
present invention, a resource graph is termed a lock graph. In
order to begin construction of a lock graph, a Java.TM. program is
provided, which consists of several sets of byte code.
[0030] Referring initially to FIG. 1, a flow diagram illustrates a
high-level deadlock detection methodology, according to an
embodiment of the present invention. The methodology begins in
block 102 in which an invocation graph is constructed having a
single root, or relevant entry point. In block 104, a lock graph is
computed, considering all possible paths of execution from the root
to the sources where a resource is acquired or requested. Path
information is retained for reporting purposes. In block 106, it is
determined if the resulting lock graph has any cycles. In block
108, any cycles are reported to the user, with associated path
information.
[0031] In preferred embodiments of the present invention a Java.TM.
byte code analysis (JaBA) system is utilized, which uses static
analysis techniques to build an invocation graph for the methods,
or functions written in the Java.TM. byte code. JaBA also generates
information about values of variables and locks. The system is flow
sensitive in that each method's control flow graph considers the
order of execution of the instructions within each basic block,
accounting for local variable kills and casting of object
references. The system is also context sensitive, because each node
in the invocation graph is uniquely identified by its calling
context, namely, the method, a set of possible receiver types, and
possible parameter types.
[0032] Each node of the invocation graph represents a method and a
particular context and contains the basic blocks of the method's
control flow graph and locations where locks are accessed or
released. The invocation graph also has an interprocedural edge (A,
B), representing the invocation of method B from within method A.
The edge extends from the instruction in A where the invocation
takes place to the initial vertex of the control flow graph of B.
The invocation graph of the present invention allows bi-directional
traversal, even though the edges in the graph are unidirectional.
Therefore, from any node n within the invocation graph, the sets of
its predecessor nodes and successor nodes may be found.
[0033] In addition to the invocation graph, a data flow analysis is
performed with precision to the level of allocation sites, where
each allocation is uniquely identified. The number of objects in a
Java.TM. program as modeled by the invocation graph is always
finite. There are a finite number of calls in the object code, and
the elements of arrays and other collections are modeled as single
elements. JaBA also produces a file indicating all the classes
examined and their hierarchical relationships.
[0034] As described above, a lock graph is given by (N, E). Each
element of N is a set of locks corresponding to objects in the
Java.TM. program. Let v .epsilon. N and w={w.sub.1,w.sub.2, . . . ,
w.sub.m} .epsilon. N, then if there exists an execution path in the
program for which a thread has acquired at least the set of locks v
and requests the set w, then (v, w.sub.i).epsilon.E,i=1, . . .
,m.
[0035] If the Java.TM. program has n locks, then in theory there
are 2.sup.n nodes, corresponding to all possible subsets of the n
elements. However, isolated nodes, nodes with no edges leaving or
entering them, may be ignored. In practice, the graph is
constructed incrementally, adding lock sets and edges as they arise
in the traversal of the program paths, and the number of nodes is
far less than the theoretical maximum.
[0036] Referring now to FIG. 2, a flow diagram illustrates a lock
graph computation methodology, according to an embodiment of the
present invention. This may be considered a detailed description of
block 104 in FIG. 1. Construction of the lock graph takes place in
two stages. In block 202, a set of nodes and edges are constructed
in conjunction with a lock set calculation algorithm that is
described in, for example, G. B. Leeman et al., "Detecting Unwanted
Synchronization in Java Programs," Tech. Rep. RC 22552, IBM Thomas
J. Watson Research Center, Yorktown Heights, N.Y., September 2002.
The lock graph computation utilizes calculated lock sets in effect
at each node of the invocation graph and within each basic block to
construct a set of nodes and edges in the lock graph, as will be
described in more detail below. In block 204, a second step, termed
post-processing, refines the graph definition.
[0037] A lock is defined as a pair (o,c), where o is an object in
the Java.sup.SM program and c, the counter, is a positive integer
bounded by a fixed constant .OMEGA.. A lock set is a collection of
locks in which all the objects o are distinct. In the invocation
graph model of a Java.TM. program, the total number of Java.TM.
objects is finite. Hence the number of different possible lock sets
for that program is finite.
[0038] Given a lock set m, plus (+) is defined, corresponding to
monitorenter, as follows: [0039] if (o, c) .epsilon. m for some c,
(o, c) in m is replaced by (o, min(c+1, .OMEGA.)); [0040]
otherwise, add (o, 1) to m.
[0041] The resulting set is m+o.
[0042] For the union (.orgate.) of a set m with a lock (o, c),
[0043] if o does not appear in any lock object of m, add (o, c) to
m; [0044] if (o, d) .epsilon. m with d<c, replace (o, d) by (o,
c) in m; [0045] if ((o, d) .epsilon. m with d=c, m remains
unchanged.
[0046] The resulting set is m .orgate. (o, c).
[0047] The + and .orgate. are extended to operations on two sets
m.sub.1 and m.sub.2 by computing m.sub.1(+or .orgate. for each o
.epsilon. m.sub.2.
[0048] In practice the use of counters rarely arises in bytecode.
Therefore, a condition of .OMEGA.=1 may be set.
[0049] The union operation expresses the fact that an invocation
graph node successor inherits the lock sets of its predecessors: if
node i has lock set m.sub.i, i=1, 2, and node 2 is a successor of
node 1, then at some point in the computation m.sub.2 will be
replaced by m.sub.1 .orgate. m.sub.2.
[0050] Referring now to FIG. 3, a lock set construction methodology
is provided, according to an embodiment of the present invention.
This may be considered a detailed description of block 202 in FIG.
2. Within this fixed-point algorithm, nodes and edges refer to
parts of the invocation graph. This methodology is performed for
each thread in the Java.TM. program; the start node is the thread's
start( ) method, and first a thread closure set is formed with all
nodes reachable from its start( ) node.
[0051] The first four steps of the methodology are initializations.
Step 1 initializes the empty lock sets and empty graphs. Step 2
initializes all structures for nodes with synchronized blocks,
which records which basic blocks contain monitorenters and
monitorexits. Step 3 initializes all lock sets based on
synchronized methods, and more specifically, computes initial
values of lock sets for nodes and edges based on synchronized
methods. Step 4 places the starting values into the queue. The
"empty" lock graph actually has one node (node 0) representing the
empty lock set.
[0052] A main loop is provided in steps 5-15 of the methodology.
The current lock set is calculated in step 7, and the lock graph is
updated, if necessary. Whenever new locks are requested, new
vertices and edges may be added. Step 8 performs intraprocedural
analysis to determine the lock sets of basic blocks and edges, see,
for example, G. B. Leeman et al. Again, this step may necessitate
updating of the lock graph. Finally, steps 9-15 perform
interprocedural analysis to compute lock sets for each edge leaving
the current node, step 10. If the lock set of the successor node is
changed, steps 11-14, the successor is added to the current path,
and they are placed onto the queue step 15. The paths are kept by
the lock graph for reporting purposes.
[0053] The refining of the graph definition through post-processing
as described in block 204 of FIG. 2, involves the examination of a
current set of vertices to generate additional edges. Recall that
the first stage ran on each thread, perhaps producing new lock
graph nodes and edges. If thread t produces an edge (p(t), s(t)),
then some execution path acquires at least the locks in the
predecessor set p(t) and requests the lock in the successor set
s(t). Similarly, suppose a second thread t' produces an edge
(p(t'), s(t')). The condition p(t) .andgate. p(t').noteq..phi.
expresses a situation that cannot occur, because Java.TM. threads
and locks satisfy the mutual exclusion property. However, if p(t)
.andgate. p(t')=.phi., then additional edges may be created which
may be of interest. Namely, for each lock m in p(t) a new node {m}
is created (unless this node already exists) and edge from {m} to
s(t) (unless such an edge already exists); the analogous operation
is performed for p(t'). Thus, block 204 consists of pair wise
inspection of threads and creation of additional nodes and edges
via this process.
[0054] A classic dining philosophers problem may be used to
illustrate the embodiments of the present invention, see, for
example, A. Silberschatz et al., "Operating System Concepts," sixth
ed., John Wiley & Sons, Inc., New York, N.Y., 2002. Referring
now to FIG. 4, Java.TM. code is shown for the classic dining
philosophers problem having four philosophers and five chopsticks,
in which two chopsticks (resources) are required for the
philosophers to eat, eventually leading to deadlock.
[0055] Lines 44-49 of the Java.TM. code of FIG. 4 create the five
philosopher objects, and the three arguments indicate the
philosopher's name, the chopstick to his left, and the chopstick to
his right, respectively. The chopsticks are expressed via strings
in lines 2-6. Each philosopher is also a thread (line 1), and the
threads are started in lines 50-54, which cause the run method
(lines 15-39) to be executed. This method models each philosopher's
behavior: he sits between two chopsticks allocated to him (line 16)
and then enters a thinking-picking-eating loop (lines 18-34), where
each action takes a random amount of time. In that loop he thinks
(lines 19-20), picks up his left chopstick (lines 21-24), picks up
his right chopstick (lines 25-28), and eats (lines 29-33). Java.TM.
synchronization blocks mirror the chopsticks' mutual exclusion,
wait for, and no preemption properties. When this program is run,
deadlock is quickly reached.
[0056] In accordance with the embodiments of the present invention,
through JaBA, objects are represented via a list of the form of:
[0057] index type class [0058] method [0059] programCounter
sourceLine
[0060] For example, the chopstick1 object is represented as: [0061]
14 NewSite Philosopher [0062] Philosopher.main([java.lang.String])
[0063] PC 0 SL 2
[0064] The index is a unique number assigned to each object. If
source code is not available, the source line entry is -1. The
important objects in the dining philosophers problem all have the
same type, class, class loader, and method. The indices, program
counters, and source line numbers are shown in the table of FIG. 5.
Additionally, a portion of the invocation graph for the dining
philosophers example is shown in FIG. 6. The example provided has
11 locks (5 philosophers, 5 chopsticks, and a Math lock), but there
are far fewer than 211 nodes, specifically, 22 nodes and 40
edges.
[0065] The progress of the first stage may be traced for the dining
philosophers example. There are five start nodes (lines 50-54)
where the methodology of FIG. 3 is applied. Note that start( ) is
actually of the form: [0066] public synchronized native [0067]
java.lang.Thread.start and thus for each start node, step 7 of FIG.
3 causes the creation of nodes 16, 1, 19, 7, and 12 in a lock
graph, which is illustrated in FIG. 7, according to the embodiment
of the present invention. These integers correspond to the objects'
indices in the table of FIG. 5. Additionally, the five edges:
[0068] (0, 1), (0, 7), (0, 12), (0, 16), (0, 19) are formed, which
say that a thread acquires at least no locks (node 0) and requests
a single lock to run the start method.
[0069] The successor of start( ) is the run method. The processing
of line 22 of FIG. 4 by Step 8 of FIG. 3 causes the creation of new
lock graph nodes 14, 2, 4, 8, and 10 in the lock graph of FIG. 7
corresponding to the five chopstick objects in the table of FIG. 5.
There are also new edges: [0070] (16, 14), (1, 2), (19, 4), (7, 8),
(12, 10), in particular from line 45 (16, 14) says that start( )
acquires at least the frege lock (16) and then requests the
chopstick1 lock (14) at line 22. Similarly, when line 26 is
analyzed, new lock sets and Java.TM. lock graph nodes: [0071]
17={16, 14}, 3={1, 2}, 20={19, 4}, 9={7, 8}, 13={12, 10} are
created, followed by edges: [0072] (17, 2), ( 3, 4), (20, 8), (9,
10), (13, 14), for example, after acquiring at least the frege and
chopstick1 locks ({16,14}, set to 17), chopstick2 (2) is requested,
resulting in edge (17, 2).
[0073] Often unexpected nodes will be generated because of the
signatures of various built-in methods. In our example the random
method (line 41) calls initRNG that has signature: [0074] private
static synchronized [0075] java.lang.Math.initRNG( )V}
[0076] Therefore, there is a new lock consisting of the class
object for the Math class, and a lock set with three elements (a
philosopher, chopstick, and the Math lock) will be generated, along
with additional nodes and edges. However, since they are of less
interest, they have not been discussed.
[0077] Block 204 of FIG. 2 does not create any new vertices.
However, the philosopher frege thread produces edge (17, 2), and
the philosopher hegel thread produces edge (3, 4). The sets 17 and
3 are disjoint, so block 402 proposes new edges ({16}, 2), {{14},
2), ({1}, 4), and ({2,} 4), which in our notation is the same as
(16, 2), (14, 2), (1, 4), and (2, 4). Edge (1, 4) already exists,
but the other three are new. It is not difficult to determine that
philosophers kant and mill produce new edges (4, 8), (7, 10), (8,
10), and philosopher plato plus any other philosopher object yield
two new edges (10, 14) and (12, 14). Still more edges arise from
the lock sets with three elements, which are not addressed in this
illustrative example.
[0078] In the dining philosophers example, exactly one cycle is
found: [0079] 2.fwdarw.4.fwdarw.8.fwdarw.10.fwdarw.14.fwdarw.2 An
example of the output produced for the dining philosophers example
in accordance with the embodiments of the present invention is
provided in FIG. 8.
[0080] When the Java.TM. lock graph has cycles, information is
reported, and the user may use this information to determine if
deadlock is present. Because static analysis often produces false
positives, each output collection must be examined. When the graph
has no cycles, that condition is strong evidence for absence of
deadlock. The user may be able to look at the threads analyzed to
see the deadlock is not present. In general, static analysis cannot
traverse all possible program executions, and in Java.TM. dynamic
features such as reflection exacerbate the problem.
[0081] A simple example of a two-way deadlock is provided in D.
Lea, "Concurrent Programming in Java Design Principles and
Patterns," Addison-Wesley, Reading, Mass., 1997. See also, C.
Demartini et al. "A Deadlock Detection Tool for Concurrent java
Programs," Software-Practice and Experience 29, 7, June 1999, pp.
577-603. However these references provide a relatively complicated
analysis. The embodiments of the present invention provide a
particularly simple analysis, by generating a lock graph with only
7 nodes, 10 edges, and 1 cycle. Exactly two nodes v and w have the
property that both (v, w) and (w, v) are edges, giving rise to the
cycle and the deadlock. Although the embodiments of the present
invention have been illustrated in the context of analyzing
Java.TM. code, they may be applied to any language that supports
monitors.
[0082] Referring now to FIG. 9, a block diagram illustrates an
exemplary hardware implementation of a computing system in
accordance with which one or more components/methodologies of the
invention (e.g., components/methodologies described in the context
of FIGS. 1-8) may be implemented, according to an embodiment of the
present invention.
[0083] As shown, the computer system may be implemented in
accordance with a processor 910, a memory 912, I/O devices 914, and
a network interface 916, coupled via a computer bus 918 or
alternate connection arrangement.
[0084] It is to be appreciated that the term "processor" as used
herein is intended to include any processing device, such as, for
example, one that includes a CPU (central processing unit) and/or
other processing circuitry. It is also to be understood that the
term "processor" may refer to more than one processing device and
that various elements associated with a processing device may be
shared by other processing devices.
[0085] The term "memory" as used herein is intended to include
memory associated with a processor or CPU, such as, for example,
RAM, ROM, a fixed memory device (e.g., hard drive), a removable
memory device (e.g., diskette), flash memory, etc.
[0086] In addition, the phrase "input/output devices" or "I/O
devices" as used herein is intended to include, for example, one or
more input devices (e.g., keyboard, mouse, scanner, video camera,
etc.) for entering data to the processing unit, and/or one or more
output devices (e.g., speaker, display, printer, etc.) for
presenting results associated with the processing unit.
[0087] Still further, the phrase "network interface" as used herein
is intended to include, for example, one or more transceivers to
permit the computer system to communicate with another computer
system via an appropriate communications protocol.
[0088] Software components including instructions or code for
performing the methodologies described herein may be stored in one
or more of the associated memory devices (e.g., ROM, fixed or
removable memory) and, when ready to be utilized, loaded in part or
in whole (e.g., into RAM) and executed by a CPU.
[0089] The embodiments of the present invention described herein
provide an automatic method to detect deadlock in languages that
support the monitor concept to achieve synchronization. It works
for both source code and byte code, because the former may be
compiled into the latter, which is analyzed. No code annotations
are required.
[0090] Although illustrative embodiments of the present invention
have been described herein with reference to the accompanying
drawings, it is to be understood that the invention is not limited
to those precise embodiments, and that various other changes and
modifications may be made by one skilled in the art without
departing from the scope or spirit of the invention.
* * * * *