Сервер зависает, когда Spring транзакционно использует синхронизированный (Object.class)

Я использую Spring с jdbc, сервер зависает, когда я использую @transactional и синхронизирован (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 миллисекунд.

После дублирования я обнаружил, что 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;
}

Анализ показал, что операторы sql для T1 и T2 одинаковы, T1 не подключен, поэтому T2 не удалось получить блокировку базы данных Oracle, но почему T1 не подключен.

Я предполагаю, что проблема в том, что я использую "synchronized (Object.class)" в методе "signForBusiness", поэтому я изменил "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>

0 ответов

Другие вопросы по тегам