我有一个使用Spring JDBC访问SQLite数据库的DAO类。我已经在DAO方法上声明了事务,因为我的服务层永远不会在事务中组合查询。
由于我并行使用了一些工作线程,但只有一个线程可以同时更新SQLite数据库,因此我使用synchronized
来序列化对DAO的访问。
首先,我从服务类外部进行同步,例如:
synchronized (dao) {
dao.update(...);
}
然后,我想我也可以摆脱外部同步并将synchronized
放在DAO方法本身上:
public synchronized void update(...) {
// Spring JDBC calls here
}
奇怪的是:我的查询现在花费了两倍的时间!
为什么?
答案 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访问。因此,不是一个连接不断重用,您将使用多个连接。我只能猜测这是如何影响性能的,但你可以尝试从一个开始尝试不同的池大小。