Reputation: 11403
I'm in the following situation.
There are several threads that can read/update MonthlySales
persistent objects. Problem is that these objects may not exist and have to be dynamically created upon request.
So, two different threads my end up creating the entity corresponding to the same key (i.e. having the same ID), thus one of them failing to commit. I don't want this to happen. I would like one of the two threads to win the race and the other one to loose, waiting until the object has been created by the other.
In other words, I do want to do serialized transactions. Should I put an explicit Java lock (i.e. synchronized
block)?
My current code is the following:
MonthlySales ms = entityManager.find(MonthlySales.class, somekey);
if (ms == null) { // two threads might enter this block altogether
ms = new MonthlySales();
// prepare ms object populating its fields with default values
entityManager.persist(ms);
entityManager.flush();
}
entityManager.lock(ms, LockModeType.PESSIMISTIC_WRITE); // lock this object
// since we are going to update it
// do something with ms object
entityManager.getTransaction().commit();
entityManager.close();
Can you help me?
Upvotes: 3
Views: 3345
Reputation: 319
Do it in two phases:
Phase 1:
get the monthly sales from the DB
if it does not exist {
try {
create it
persist it
flush
} catch(exception when already exists) {
// ignore
}
} else {
flush
}
Phase 2 in a transaction:
get the monthly sales from the DB
lock it
update it
commit
Upvotes: 0
Reputation: 38193
One way of avoiding a race condition is to let the thread / process / etc with the lowest ID win.
I believe you can access the thread ID using
long threadID = Thread.currentThread().getId();
from within the thread in Java. This is a better race condition solution than blocking the other threads, because that would defeat the purpose of using more than one thread.
See the Critical-Section Bakery Algorithm:
http://www.basicsofcomputer.com/critical_section_problem_in_operating_system.htm
In the case of JPA, according to here and here, the best practice approach seems to be trying to modify things at the same time, and catching exceptions if things don't work out.
Upvotes: 1