Spring事务及其与synchronized关键字的交互

时间:2012-02-22 08:55:45

标签: java spring jdbc transactions spring-jdbc

我有一个使用Spring JDBC访问SQLite数据库的DAO类。我已经在DAO方法上声明了事务,因为我的服务层永远不会在事务中组合查询。

由于我并行使用了一些工作线程,但只有一个线程可以同时更新SQLite数据库,因此我使用synchronized来序列化对DAO的访问。

首先,我从服务类外部进行同步,例如:

synchronized (dao) {
    dao.update(...);
}

然后,我想我也可以摆脱外部同步并将synchronized放在DAO方法本身上:

public synchronized void update(...) {
    // Spring JDBC calls here
}

奇怪的是:我的查询现在花费了两倍的时间!

为什么?

2 个答案:

答案 0 :(得分:1)

嗯,一个显而易见的区别是:

synchronized (dao) {
    // here you are synchronizing on the transactional proxy
}

public synchronized void update(...) {
    // and here you are synchronizing on the target class, *inside* the proxy
}

这取决于你的其他代码,但这是明显的区别。

答案 1 :(得分:0)

我的猜测是你的更新方法或整个类用Transactional注释或由事务代理通过其他方式包装。这意味着无论何时调用dao的方法,事务代理都会从池中检索数据库连接,打开事务然后调用实际方法。

在您的第一个场景中,您甚至在到达代理之前进行同步,因此不会发生连接和事务魔术。在第二种情况下,您将在此之后进行等待呼叫。

如果有多个线程尝试执行同步更新,则只有一个线程正在执行更新,其余线程将首先打开新连接,然后等待dao访问。因此,不是一个连接不断重用,您将使用多个连接。我只能猜测这是如何影响性能的,但你可以尝试从一个开始尝试不同的池大小。