We currently have a mixed strategy for locking the L2 cache. Whenever an object is accessed we lock the cache, and similarly when we are doing the update in txn.commit. Similarly when updating the CachedPC object in JDOStateManagerImpl we lock the PC object that is part of the CachedPC. If we have bidirectional relations this could easily lead to
Thread 1 : locks A and waits for B
Thread 2 : locks B and waits for A
The locking strategy needs rewriting, and locking the L2 cache itself as little as possible. Likely the best way would be to just lock the CachedPC when accessing some info, though even this would not prevent reads from fields of the contained "pc" while something else was updating it.