锁定释放导致Neo4j死锁

时间:2015-04-18 13:49:33

标签: java multithreading neo4j

考虑包含用户和新闻项目的社交网络图。 有多种方法可以修改图形,并且可以同时调用它们 我实现了一个锁定管理器,以避免任何死锁。它锁定从最低到最高用户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]]

如您所见,事务锁定了两个用户节点(id 1和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的调用与相应节点的新锁定之间是否存在延迟?

1 个答案:

答案 0 :(得分:1)

锁定实际上只是在事务结束时才会释放。

这就是为什么在调用tx.close()之前它仍然存在锁定。