Reputation: 78
I'm developing an application with some kind of 'facebook like' feature. Every time that a content published by a user is 'liked' he will have his punctuation increased. This app will be used by a large number of users around the company, so We are expecting a lot of concurrent updates to the same row.
simplified code
Punctuation(
userId NVARCHAR2(32),
value NUMBER(10,0)
)/
public class Punctuation(){
private String userId;
private int value;
public Punctuation(final String userId, final int value){
this.userId = userId;
this.value = value;
}
public String getUserId();
public int getValue();
}
//simplified code
public final class PunctuationController{
private PunctuationController(){}
public static void addPunctuation(final Punctuation punctuation){
final Transaction transaction = TransactionFactory.createTransaction();
Connection conn = null;
PreparedStatment statment = null;
try{
synchronized(punctuation){
transaction.begin();
conn = transaction.getConnection();
statment = conn.preparedStatment("UPDATE Punctuation SET value = value + ? where userId = ?");
statment.setString('1', punctuation.getUserId());
statment.setInt('2', punctuation.getValue());
transaction.commit();
}
}catch (Exception e){
transaction.rollback();
}finally{
transaction.dispose();
if(statment !=null){
statment.close();
}
}
}
We are afraid of deadlocks during updates. Oracle allows to make the sum on a single query, I don't have to retrieve the value and make a second query to update with a new value, that's good. Also reading some other posts here, They said to create a synchronized block to lock an object, and let Java handle the synchronization between different threads. I choose the punctuation instance the method receives, this way I imagine that different combinations of user and value will allow concurrent acess to this methods, but will block an instance with same values (Do I have to implement equals() on Punctuation?)
Our database is Oracle 10g, Server Weblogic 11g, Java 6 and Linux (I dont know which flavor).
Thank you in advance!
Upvotes: 1
Views: 2012
Reputation: 3170
you need to use optimistic lock pattern. take a look here for more details http://docs.jboss.org/jbossas/docs/Server_Configuration_Guide/4/html/The_CMP_Engine-Optimistic_Locking.html
And probably this http://docs.jboss.org/jbossas/docs/Server_Configuration_Guide/4/html/The_CMP_Engine-Optimistic_Locking.html which is more low level details
After identification of concurrent issue using optimistic lock, you may want to prefer re-trying - you have a full control what to do
Upvotes: 0
Reputation: 691715
You're wrong on your synchronization strategy. synchronized
uses the intrinsic lock of the object between parentheses. If you have two Punctuation
instances that you might consider equal because they refer to the same user_id
, Java doesn't care: 2 objects, so 2 locks, so no mutual exclusion.
I really don't see why the above, without the synchronized
, could generate deadlocks: you're updating a single row in the table. You could have a deadlock if you had two concurrent transaction with one updating user1, then user2, and the other one updating user2, then user1. But even then, the database would detect the deadlock and throw an exception for one of the transactions.
Upvotes: 3