我使用Spring和jdbc,当我使用@transactional和synchronized(Object.class)时服务器挂起。
代码简化如下:
package com.zjipst.immigration.review.service.impl;
@Service
public class ReviewsImpl implements Reviews {
......
@Transactional
public String signForBusiness(String barcodes) {
synchronized (Object.class){
dataDAO.setSigned(barcodes);
}
return "success";
}
......
}
package com.zjipst.immigration.review.dao.impl;
@Repository
public class DataDAOImpl implements DataDAO {
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
@Autowired
public void setDataSource(DataSource dataSource) {
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(
dataSource);
}
......
@Override
public int setSigned(String barcode) {
String sql = "update BUSINESS set S_TIMES = (S_TIMES+1) where BARCODE = :barcode";
return namedParameterJdbcTemplate.update(sql,
new MapSqlParameterSource("barcode", barcode));
}
......
}
服务器挂起当两个线程T1和T2调用相同的方法“signForBusiness”并且间隔小于20毫秒。
在dubuging之后我发现T2锁定在方法“setSigned”:
return namedParameterJdbcTemplate.update(sql,new MapSqlParameterSource("barcode", barcode));
T1锁定在“signForBusiness”方法:
return "success"
通过单步调试,我发现T1锁定在“this.advice.afterReturning(retVal,mi.getMethod(),mi.getArguments(),mi.getThis());”:
package org.springframework.aop.framework.adapter;
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
通过分析,我发现T1和T2的sql语句是相同的,T1是uncommited,所以T2无法获得oracle数据库锁,但为什么T1不通信。
我想问题是我在方法“signForBusiness”中使用“synchronized(Object.class)”,所以我将“synchronized(Object.class)”修改为“synchronized(this)”,并且
问题解决了,同步也工作了。
如果有人可以解释或给出任何建议,我非常感激。
顺便说一句,我正在使用以下配置。
的applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.zjipst.immigration.review" />
<aop:aspectj-autoproxy />
</beans>
的applicationContext-ds.xml中
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${db.driverClassName}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
<property name="initialSize" value="${db.initialSize}" />
<property name="minIdle" value="${db.minIdle}" />
<property name="maxIdle" value="${db.maxIdle}" />
<property name="maxTotal" value="${db.maxTotal}" />
<property name="testOnBorrow" value="${db.testOnBorrow}" />
<property name="validationQuery" value="${db.validationQuery}" />
<property name="maxWaitMillis" value="${db.maxWaitMillis}" />
</bean>
<context:property-placeholder location="classpath:jdbc.properties.dev"
ignore-unresolvable="true" />
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>