今天,我遇到了一个问题,该问题推测一种方法未释放锁,从而导致了死锁情况。
环境:
这是tomcat上的网络应用程序,当用户从UI调用服务器时,线程将进入servlet。Servlet具有自动装配的spring bean,其中通过servlet中的方法调用bean中的方法。
该方法是同步的,它所做的就是通过spring jdbc模板和String列表进行批量插入(Oracle DB)。(2行代码,1个jdbcTemplate批处理更新和一个日志)
在测试我的浏览器挂起后,我关闭了它,但没有人能够输入同步方法。
在这种环境下使用同步时,在这种情况下我是否需要记住一些事情?有人对可能发生的事情有猜测吗?如何保证一段时间后将释放锁?
谢谢
public class LockManager {
private JdbcTemplate jdbcTemplate;
private static final Log LOG = LogFactory.getLog(LockManager.class);
/* synchronized to guarantee that only one thread at a time is inserting. */
public synchronized void lockTransactions(final List<String> idList, final String userID) throws MyException{
try{
final Timestamp occuranceTime = new Timestamp(System.currentTimeMillis());
jdbcTemplate.batchUpdate(INSERT_ID, new LockInsertBatchPreparedStatementSetter(idList,userID, occuranceTime));
LOG.info("Lock Rows completed. ID List size="+idList.size());
}catch(Exception e){
handleInsertException(e);
}
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/* Throw appropriate exception. */
private void handleInsertException(final Exception e) throws MyException{
String message = e.getMessage();
MyException me = null;
if(message.contains("ORA-00001")){
me= new MyException(ExceptionMessage.LOCK_CONSTRAINT.getMessage(),e);
}else{
me= new MyException(ExceptionMessage.LOCK_ERROR.getMessage(),e);
}
LOG.error("Exception while locking IDs",me);
throw me;
}
private class LockInsertBatchPreparedStatementSetter implements BatchPreparedStatementSetter{
private List<String> idList;
private String userID;
private Timestamp occuranceTime;
private final Log LOG = LogFactory.getLog(LockInsertBatchPreparedStatementSetter.class);
public LockInsertBatchPreparedStatementSetter(final List<String> idList, final String userID, final Timestamp occuranceTime){
this.idList = idList;
this.userID = userID;
this.occuranceTime=occuranceTime;
}
@Override
public int getBatchSize() {
return idList.size();
}
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
String thisID= idList.get(i);
ps.setString(1, thisID);
ps.setString(2, userID);
ps.setTimestamp(3, occuranceTime);
LOG.info("Attempting to Lock ID:"+thisID+ " for user:"+userID);
}
}
}
首先,您应确保同步方法仅包含需要同步的代码。
其次,如果您正在执行如上所述的类似DB写的操作(批处理插入(Oracle DB)),请确保对此类操作设置超时。如果您的批处理插入时间太长,可能由于多种原因而发生。超时应该有助于快速完成任务,或者直接退出而不完成任务。
同步方法内部的任何缓慢操作,肯定会成为其他尝试进入该方法的线程的杀手。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句