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

Java Spring事务及其与synchronized关键字的交互,java,spring,jdbc,transactions,spring-jdbc,Java,Spring,Jdbc,Transactions,Spring Jdbc,我有一个DAO类,它使用SpringJDBC访问SQLite数据库。我已经在DAO方法本身上声明了事务,因为我的服务层从不在事务中组合查询 由于我并行使用几个工作线程,但只有一个线程可以同时更新SQLite DB,因此我使用synchronized来序列化对DAO的访问 首先,我从我的服务类外部同步,例如: synchronized (dao) { dao.update(...); } 然后,我想我还是放弃外部同步,把synchronized放在DAO方法本身上为好: public s

我有一个DAO类,它使用SpringJDBC访问SQLite数据库。我已经在DAO方法本身上声明了事务,因为我的服务层从不在事务中组合查询

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

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

synchronized (dao) {
    dao.update(...);
}
然后,我想我还是放弃外部同步,把
synchronized
放在DAO方法本身上为好:

public synchronized void update(...) {
    // Spring JDBC calls here
}
奇怪的是:我现在的查询时间是以前的两倍


为什么?

我猜是您的更新方法,或者整个类被事务性的注释,或者被事务性代理通过其他方式包装。这意味着无论何时调用dao的方法,事务代理都会从池中检索db连接,打开一个事务,然后调用真正的方法

在第一个场景中,您甚至在到达代理之前就进行了同步,因此不会发生连接和事务魔法。在第二个场景中,您在这之后执行等待呼叫


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

好吧,一个明显的区别是:

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
}

这意味着什么取决于您的其他代码,但这是明显的区别。

自从您将synchronized从服务方法移动到DAO方法以来,它们花费了两倍的时间?我使用绑定为4的BoundedExecutor,因此有4个线程进行计算,然后并行更新DB。我对C3p0连接池进行了一些测试,结果如下:池中的1个连接->7秒,2个连接->13s,3个连接->13s,10个连接->13s和256个连接->13s。因此,当连接池大小大于1时,性能实际上会下降。有什么想法吗?如果你只做更新,你可以尝试摆脱同步,使用一个连接池。至于多个连接的性能比单个连接差,这一点非常清楚。事实上,您一次只允许一个事务,这样您就不需要管理这些额外连接的开销。虽然我更希望时间增加到4个连接,然后保持不变。我猜在后一种情况下,当DAO的
update()
方法返回时,1)其中的
synchronized
块结束,2)事务代理提交其事务,因此它仍然有效地同时尝试更新SQLite DB,也就是说,这正是我试图阻止的。这听起来可信吗?