考虑一个包含用户和新闻项的社交网络图。有多个方法可以修改图形,并且可以同时调用它们。
我实现了一个锁管理器来避免任何死锁。它锁定从最低到最高排序的用户id,该用户id作为属性存储在用户节点中。锁以相反的顺序释放。
然而,当并发执行一个特定的方法时,我得到了下面的DeadLockDetectedException:
org.neo4j.kernel.TopLevelTransaction@41aaf8e9:
locking manager locked [NODE(0) [#1], NODE(5) [#3]]
org.neo4j.kernel.TopLevelTransaction@41aaf8e9:
locking manager released [NODE(5) [#3], NODE(0) [#1]]
org.neo4j.kernel.TopLevelTransaction@41aaf8e9:
locking manager locked [NODE(1) [#2]
Exception in thread "Thread-3" org.neo4j.kernel.TopLevelTransaction@6242de17:
org...DeadlockDetectedException:
LockClient[18] can't wait on resource RWLock[NODE(1)] since =>
LockClient[18] <-[:HELD_BY]- RWLock[NODE(5)] <-[:WAITING_FOR]- LockClient[20] <-[:HELD_BY]- RWLock[NODE(1)]
org.neo4j.kernel.TopLevelTransaction@7007944f:
locking manager locked [NODE(1) [#2], NODE(5) [#3]]如您所见,一个事务锁定两个用户节点(id1和3)。稍后,它尝试锁定另一个用户节点(id为2),但无法获得此锁:有第二个事务锁定了id为2的用户,并正在等待锁定id为3的用户。
看似合理,这将是一个死锁。
然而,代码和前面的日志消息讲述了另一个故事:在事务尝试锁定id为2的用户之前,它释放了之前获得的两个锁。下面是相应的代码:
Transaction tx = graph.beginTransaction();
// locks NODE(0) and NODE(5)
Lock[] locks = LockManager.lock(tx, following, followed);
boolean result = removeFollowship(following, followed);
// releases NODE(5) and NODE(0)
LockManager.releaseLocks(locks);
...
// tries to lock NODE(1)
List<Lock> locks = LockManager.lock(tx, replicaLayer);
try {
return addStatusUpdate(author, statusUpdate);
} finally {
LockManager.releaseLocks(locks);
}
...
tx.success();锁管理器通过tx.acquireWriteLock(node)锁定节点,并通过lock.release()释放锁。
有什么我不知道的吗?例如,调用lock.release和新锁定相应节点之间是否存在延迟?
发布于 2015-04-19 00:40:55
锁实际上是在事务完成时释放的。
这就是为什么在你的tx.close()被调用之前,它仍然持有锁。
https://stackoverflow.com/questions/29718245
复制相似问题