My problem with SynchronizationRegistry is that this is a write-only class; while all the operations triggered by #afterUpdate/#unlockItem could run in parallel. If these are synchronous, running sequentially adds up a lot of latency. However, I can't register single synchronization that would wait for all operations triggered by #afterUpdate. Besides, if I register these synchronizations manually, I can't be sure about the order of execution - #afterUpdate is called from a synchronization as well. I am not even sure if it is legal to register a synchronization from another synchronization. And, as you've said, the registry is local to the session - while we are more interested (in the sense of parallelizing operations) in the scope of transaction than a session. I'd also like to acquire the locks (#lockItem) in parallel, and wait for all of them to be acquired before the DB commit. I could achieve that by registering another Synchronization that would wait for the async operation to finish in #beforeCompletion. Maybe a synchronization is lightweight enough, and I could really do that for each of them... About "synchronous" strategies: Do you assume that JTA based Cache implementations can provide the same level of isolation as DB? Maybe I was too strict, assuming serializable* isolation from the database and implementing the 2LC in a way that even non-serializable Cache will keep up. For example EhCache can provide only read committed, so I guess that if you use EhCache 2LC with different hibernate.connection.isolation, you're (silently) doomed. Luckily, JCache seems to go the async way and therefore it behaves correctly (AFAIU). *Serializable or Repeatable reads: while I understand RR as "not allowing non-repeatable reads" (e.g. by caching the read values and transparently providing those cached values), some definitions mean "placing shared lock on read data" and therefore blocking any writes from other transactions. More interestingly, this also means that when the data is being written, noone can read that until the transaction completes. For example Infinispan does never lock for reads, therefore to achieve shared-lock-grade RR the 2LC implementation must force the entity to be not present during the transaction commit. |