Lock Manager Differences Explained

Work in Progress


  • uses Java intrinsic locks, i.e. ’synchronized’. this might not perform that well on multiprocessor machines
  • uses Thread.sleep() and Thread.interrupt() to wait for locks. this involves context switches which can be expensive
  • keeps global graph or all locks to detect deadlocks. this is a shared data structure that needs to be updated on every lock operation, so again synchronization overhead
  • creates lock clients for every new started transaction


  • uses compare-and-set instructions (AtomicInteger, AtomicLong) and concurrent non-blocking data structures (ConcurrentHashMap) instead of synchronization. they should give better scaling
  • uses a combination of busy-waits and Thread.sleep() to wait for locks. this should theoretically give less context switches
  • has no global resource to detect deadlocks. each lock client has a local unsynchronized bit-set for deadlock detection. so there is no global shared resource to update
  • pools lock clients so newly created transactions can just take them from a thread-local storage
  • bit-set used for deadlock detection is not synchronized but is updated and read from different threads. this racy access is on purpose for performance but it leads to false-positive deadlocks

Generally speaking you should not need to change the default lock_manager but to do so would require you to editing the $NEO4J_HOME/conf/neo4j.conf (3.x) or $NEO4J_HOME/conf/neo4j.properties (2.x) and include


and then restart Neo4j. ”’

  • Last Modified: 2020-10-22 22:13:22 UTC by Dana Canzano.
  • Relevant for Neo4j Versions: 2.3, 3.0.
  • Relevant keywords lock,performance.