Java中oracle表的多线程并发更新
我正在开发一个具有“类似facebook”功能的应用程序。每当用户发布的内容被“喜欢”时,他就会增加标点符号。该应用程序将被公司内的大量用户使用,因此我们希望同一行有大量并发更新
简化代码
用户标点表
Punctuation(
userId NVARCHAR2(32),
value NUMBER(10,0)
)/
Java代码
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();
}
}
}
我们担心更新过程中出现死锁。Oracle允许在单个查询中进行求和,我不必检索值并进行第二次查询以更新新值,这很好。他们还阅读了其他一些帖子,他们说要创建一个同步块来锁定一个对象,并让Java处理不同线程之间的同步。我选择该方法接收的标点符号实例,这样我可以想象,用户和值的不同组合将允许并发访问该方法,但将阻止具有相同值的实例(我必须对标点符号实现equals())
我们的数据库是Oracle 10g、服务器Weblogic 11g、Java 6和Linux(我不知道是哪种风格)。
提前谢谢
# 1 楼答案
你的同步策略错了
synchronized
在括号之间使用对象的固有锁。如果你有两个{{CD2}}实例,你可能会认为它们是相等的,因为它们引用了相同的^ {CD3}},java不关心:2个对象,所以2个锁,所以不互斥。p>我真的不明白为什么上面没有
synchronized
会产生死锁:您正在更新表中的一行。如果有两个并发事务,一个更新user1,然后是user2,另一个更新user2,然后是user1,那么可能会出现死锁。但即使这样,数据库也会检测到死锁,并为其中一个事务抛出异常# 2 楼答案
你需要使用乐观锁模式。请查看此处以了解更多详细信息http://docs.jboss.org/jbossas/docs/Server_Configuration_Guide/4/html/The_CMP_Engine-Optimistic_Locking.html
这可能是更低级的细节
在使用乐观锁识别并发问题后,您可能希望重新尝试——您完全可以控制要做什么