我有一个java方法调用Web服务并根据响应对数据库进行更改。我的任务是在多个用户同时使用此应用程序时消除并发错误。
我试图整天使用各种类型的数据库锁定,但没有任何效果。我终于尝试在进程请求方法中使用synchronized,这一切都奏效了。
我的整个应用程序都是单线程的。为什么synchronized会解决这个问题?
编辑:添加了代码。
public class ProcessMakePaymentServlet extends HttpServlet {
private DbBean db = new DbBean();
protected synchronized void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// defining variables...
try {
// initialize parameters for invoking remote method
db.connect();
startTransaction(); //autocommit=0; START TRANSACTION;
// process debit
//this method gets the method using a select...for update.
//it then updates it with the new value
successfulDebit = debitAccount(userId, amt);
if (successfulDebit) {
// contact payment gateway by invoking remote pay web service method here.
// create new instances of remote Service objects
org.tempuri.Service service = new org.tempuri.Service();
org.tempuri.ServiceSoap port = service.getServiceSoap();
// invoke the remote method by calling port.pay().
// port.pay() may time out if the remote service is down and throw an exception
successfullyInformedPaymentGateway = port.pay(bankId, bankPwd, payeeId, referenceId, amt);
if (successfullyInformedPaymentGateway) {
// insert payment record
recordPaymentMade(userId, amt, referenceId);
//call to the database to record the transaction. Simple update statement.
out.println("<br/>-----<br/>");
//getTotalPaymentMade does a select to sum all the payment amounts
out.println("Total payment made so far to gateway: " + getTotalPaymentMade());
commitTransaction();// calls COMMIT
db.close(); //connection closed.
} else {
rollbackTransaction();//calls ROLLBACK
db.close();
successfulDebit = false;
out.println("<br/>-----<br/>");
out.println("Incorrect bank details.");
}
} else {
rollbackTransaction();//calls ROLLBACK
db.close();
out.println("<br/>-----<br/>");
out.println("Invalid payment amount.");
}
} catch (Exception ex) {
try {
rollbackTransaction();//calls ROLLBACK
db.close();
} catch (Exception ex1) {
}
}
}
答案 0 :(得分:2)
我的整个应用程序都是单线程的。为什么同步解决 此?
不,它不是单线程的。 Web服务由接收客户端请求的多个线程调用。
Web服务方法实现必须处理所有同步问题,与接收多个请求的servlet实现相同,必须注意确保线程安全。
在您的情况下,通过添加synchronized,您确保Web服务客户端请求的并发处理不会因线程问题而导致损坏,并且您实际上是序列化客户端请求(以及对数据库的访问)。
你还没有发布任何代码来查看你做错了什么,但是由于web方法级别的同步解决了你的问题,你要么没有像你说的那样在数据库级别进行同步,要么线程问题损坏公共变量在访问数据库的Web服务层。
通过Web方法的synchronizing
,代码是线程安全的,但性能会恶化,因为您一次只能为1个客户端服务。
取决于您的要求
答案 1 :(得分:0)
将private DbBean db = new DbBean();
移到servlet方法中,这应该可以解决问题并发问题:
protected void processRequest(HttpServletRequest request, ...) {
// defining variables...
DbBean db = new DbBean();
...
}
尽管如此,您应该正确清除finally
块中的所有数据库资源。一个相当简单的例子,但我希望你明白我的意思:
protected void processRequest(HttpServletRequest request, ...) {
// defining variables...
DbBean db = null;
boolean commit = false;
try {
db = new DbBean();
} catch (SomeException e) {
commit = false;
} finally{
db.release(commit); /* close database connection => java.sql.Connection#close() */
}
...
}