Description:
More for http://bugs.mysql.com/bug.php?id=14972 (not being the original submitter, I can't change its status)
Codebase: Connector/J 5.0.0.-beta (timestamp in the zip around Dec 2005, that is after 14972)
I have had the following deadlock arise bewteen
ServerPreparedStatement.serverPrepare and Connection.unregisterStatement
(annotated stacktrace below) which looks similar to the original bug report.
This isn't the only one I've found: below ------ I include another I turned
up.
The trouble is a deadly embrace caused by the order locks are obtained. The
lock order is:
PatternStage-41:
connection (outer)
this.connection.getMutex()
Thread-23 lock
connection.getMutex()
connection
Thread [PatternStage-41] (Suspended)
ServerPreparedStatement.serverPrepare(String) line: 1311
**** synchronized (this.connection.getMutex()) {
ServerPreparedStatement.<init>(Connection, String, String) line: 316
Connection.prepareStatement(String, int, int) line: 4377
Connection.prepareStatement(String) line: 4315
**** synchronized method
SQLCache.doPrepareSQLStatement(String) line: 289
SQLCache.getPreparedSQLStatement(String, String[]) line: 271
SQLCache.getPreparedSQLStatement(String, String) line: 318
PSet_ReifStore_RDB.findReifTripleMatch(TripleMatch, IDBID) line: 177
SpecializedGraphReifier_RDB.find(TripleMatch,
SpecializedGraph$CompletionFlag) line: 414
GraphRDB.graphBaseFind(TripleMatch) line: 431
GraphRDB(GraphBase).find(TripleMatch) line: 224
GraphRDB(GraphBase).graphBaseFind(Node, Node, Node) line: 244
GraphRDB(GraphBase).find(Node, Node, Node) line: 241
QueryTriple$SimpleApplyer.find(Domain) line: 141
QueryTriple$SimpleApplyer.applyToTriples(Domain, Matcher, StageElement)
line: 145
StageElement$FindTriples.run(Domain) line: 50
PatternStage(PatternStageBase).run(Pipe, Pipe, StageElement) line: 43
PatternStageBase$1.run() line: 53
Thread [Thread-23] (Suspended)
Connection.unregisterStatement(Statement) line: 5380
**** synchronized
ServerPreparedStatement(Statement).realClose(boolean, boolean) line: 1863
ServerPreparedStatement(PreparedStatement).realClose(boolean, boolean) line:
1722
**** inside synchronized (this.connection.getMutex())
ServerPreparedStatement.realClose(boolean, boolean) line: 906
ServerPreparedStatement.close() line: 467
DBQueryStage.run(Pipe, Pipe) line: 111
DBQueryStage$1.run() line: 143
----------------------------
Abbreviated stack trace showing the two threads that seem to be deadlocked:
Jena-Misc DBtest [Java Application]
dev.DBtest at localhost:3929
Thread [main] (Suspended)
Thread [Thread-1] (Suspended)
Connection.getCatalog() line: 3194
*** synchronized
ServerPreparedStatement(PreparedStatement).execute() line: 709
*** inside synchronized (this.connection.getMutex())
DBQueryStage.run(Pipe, Pipe) line: 76
DBQueryStage$1.run() line: 136
Thread [PatternStage-4] (Suspended)
Thread [Thread-2] (Suspended)
ServerPreparedStatement.serverPrepare(String) line: 1312
*** inside synchronized (this.connection.getMutex())
ServerPreparedStatement.<init>(Connection, String, String) line:
316
Connection.prepareStatement(String, int, int) line: 4377
*** synchronized
Connection.prepareStatement(String) line: 4315
DBQueryStage.run(Pipe, Pipe) line: 64
DBQueryStage$1.run() line: 136
C:\Program Files\Java\jdk1.5.0_06\bin\javaw.exe (26-Apr-2006 17:02:54)
How to repeat:
This has been difficult to cut down to something small. It currently happens everytime with our test [*] suite but reducing the test suite tends to change the situation. It happens on both 2CPU workstations and 1CPU portables running Java 1.5 or 1.4 on Windows XP
[*] http://jena.sourceforge.net - An RDF framework.
Suggested fix:
A possible fix might be to have only one lock object
(the connection), so
synchronized (this.connection.getMutex()) becomes
synchronized (this.connection)
(in Connection, ServerPreparedStatement etc)
This has the same effect as
Object getMutex() {
...
return this ;
}