title: Neo4j deadlock for relationship creation between nodes locked in same transaction
body: <p>My Neo4j server throws DeadlockDetectedExceptions when executing concurrent requests and I can not figure out why.</p>
  
  <p>The following code is called by the server plugin invoked by client REST requests and happens in a single transaction.</p>
  
  <pre><code>  Node nFollowing = loadUser(idFollowing);
    Node nFollowed = loadUser(idFollowed);
  
    // locking order to avoid deadlocks
    if (Long.valueOf(idFollowing) &lt; Long.valueOf(idFollowed)) {
      tx.acquireWriteLock(nFollowing);
      tx.acquireWriteLock(nFollowed);
    } else {
      tx.acquireWriteLock(nFollowed);
      tx.acquireWriteLock(nFollowing);
    }
  
    // create relationship if not present
    for (Relationship followship : nFollowing.getRelationships(
      EdgeType.FOLLOWS, Direction.OUTGOING)) {
      if (followship.getEndNode().equals(nFollowed)) {
        return;
      }
    }
    nFollowing.createRelationshipTo(nFollowed, EdgeType.FOLLOWS);
  </code></pre>
  
  <p>Although I thought about deadlocks the following exception is thrown, indicating that a deadlock occurred when the relationship is being created.</p>
  
  <p>Exception (reduced slightly):</p>
  
  <pre><code>"ForsetiClient[78] can't acquire ExclusiveLock{owner=ForsetiClient[73]} on  
    RELATIONSHIP(49), because holders of that lock are waiting for ForsetiClient[78].\n
    Wait list:ExclusiveLock[ForsetiClient[73] waits for [73, 78, ]]",
  "exception" : "DeadlockDetectedException",
  "fullname" : "org.neo4j.kernel.DeadlockDetectedException",
  "stacktrace" : [
    "org.neo4j.kernel.ha.lock.forseti.ForsetiClient.markAsWaitingFor(ForsetiClient.java:611)",
    "org.neo4j.kernel.ha.lock.forseti.ForsetiClient.acquireExclusive(ForsetiClient.java:190)",
    "org.neo4j.kernel.impl.nioneo.xa.TransactionalRelationshipLocker.getWriteLock(TransactionalRelationshipLocker.java:33)",
    "org.neo4j.kernel.impl.core.NodeProxy.createRelationshipTo(NodeProxy.java:455)",
    "de.uniko.sebschlicht.neo4j.graphity.WriteOptimizedGraphity.addFollowship(WriteOptimizedGraphity.java:40)",
    "de.uniko.sebschlicht.neo4j.graphity.Graphity.addFollowship(Graphity.java:115)",
    "de.uniko.sebschlicht.neo4j.GraphityBaselinePlugin.follow(GraphityBaselinePlugin.java:38)",
    "org.neo4j.server.rest.web.ExtensionService.invokeGraphDatabaseExtension(ExtensionService.java:134)",
    "org.neo4j.server.rest.transactional.TransactionalRequestDispatcher.dispatch(TransactionalRequestDispatcher.java:139)"
  ]
  </code></pre>
  
  <p>I can not understand why: I already have a lock for both <code>nFolloing</code> and <code>nFollowed</code>. Indeed the deadlock does not target the node lock but the relationship lock. As the relationship gets only created when it was not already present, the lock holder must be the current one.</p>
  
  <p>If that's right the lock holder is waiting for itself.
  How can I avoid that or what else is the exception trying to say?</p>
  
  <p>Just in case:
  I do not want to use <code>synchronized</code> blocks which is <a href="http://docs.neo4j.org/chunked/milestone/transactions-deadlocks.html" rel="nofollow">suggested</a> and also <a href="http://docs.neo4j.org/chunked/stable/tutorials-java-embedded-unique-nodes.html#tutorials-java-embedded-unique-get-or-create-with-factory" rel="nofollow">marked as to be avoided</a> by Neo4j as it would slow down my service a lot and I do not expect those concurrent requests to happen very often.</p>