我有一个方法,其中一些数据库插入操作正在使用hibernate发生,我希望它们是线程安全的。该方法在参数中获取一些数据,并且有时可能在同一时间点使用相同的数据进行两次调用。
由于性能下降,我无法锁定这些表。任何人都可以建议使该方法同步解决问题吗?
答案 0 :(得分:4)
同步方法将确保一次只能由一个线程访问。如果这个方法是你写入数据库的唯一方法,那么是的,这将阻止两个线程同时写入。但是,您仍然需要处理具有相同数据的多个插入操作的事实。
答案 1 :(得分:1)
你应该让Hibernate处理并发,这就是它的意图。不要以为Hibernate会锁定任何东西:它正是为了这个目的而支持optimistic transactions。从以上链接引用:
与高并发性和高可伸缩性一致的唯一方法是使用版本控制的乐观并发控制。版本检查使用版本号或时间戳来检测冲突的更新并防止丢失更新。 Hibernate提供了三种编写使用乐观并发的应用程序代码的方法。
答案 2 :(得分:1)
数据库并发由事务处理。事务具有原子一致性隔离耐用(ACID)属性。它们在同时访问数据库的程序之间提供隔离。在Spring框架的Hibernate DAO模板中,有一些用于数据库上CRUD操作的单行方法。单独使用时,不需要通过方法同步。如果您需要使用特定的传播设置,rollbackFor设置,隔离设置将“您的方法”声明为事务性,Spring提供声明性(XML),编程和注释元数据驱动的事务管理。因此,在“您的方法”中,您可以执行多次保存,更新,删除等操作,并且ORM将确保使用您在元数据中提供的事务设置执行它。
另一个问题是线程必须锁定参与事务的所有对象。否则事务可能会失败或ORM将持久存在过时的数据。在另一种情况下,由于锁定顺序,它可能导致死锁。我认为这才是真正回答你的问题。
对象a和b都有一个Lock类型的实例变量。布尔标志可用于指示事务的成功。如果客户端代码失败,则可以重试相同的事务。
if (a.lock.tryLock()) {
try {
if (b.lock.tryLock()) {
try {
// persist or update object a and b
} finally {
b.lock.unlock();
}
}
} finally {
a.lock.unlock();
}
}
使用synchronized方法的问题在于它锁定整个Service或DAO类,使其他服务方法对其他线程不可用。通过在对象上使用单独的锁,我们可以获得细粒度并发的优势。
答案 3 :(得分:0)
没有。此方法可能使用其他方法和对象,这可能不是线程安全的。 synchronized
使线程一次只使用该方法的对象monitor
,因此它使线程安全成为对象的方法。
如果您确定所有其他线程仅对此方法使用共享功能,那么将其设为synchronized
就足够了。
答案 4 :(得分:0)
选择最佳策略取决于体系结构,有时提高性能似乎更容易使用方法同步的技巧,但这是不好的方法。
毫无疑问,您应该使用事务,如果使用该策略您遇到性能问题,则应优化数据库查询或数据库结构。
请记住,“同步”应尽可能原子化。