我正在维护一个非常老的应用程序,最近我遇到了一个多线程"错误. 这里,在一种方法中,要向数据库中插入值,首先要检查记录是否存在,然后,如果不存在,则将其插入数据库中.
I'm maintaining a very old application, and recently I came across a 'multi thread' bug. Here, in a method, to insert a value into a db, the record is first checked that it exists or not, then if it does not exist, it is inserted into the db.
createSomething(params) { .... .... if( !isPresentInDb(params) ) { ..... ..... ..... insertIntoDb(params) } ... }此处,当多个线程调用此方法时,两个或多个具有相同参数的线程 可能会通过isPresentInDb检查,一个线程成功插入,其他线程失败.
Here when multiple threads invoke this method, two or more threads with same params may cross the isPresentInDb check, one thread inserts successfully, the other threads fail.
为解决此问题,我将两个数据库交互都封装在单个synchronized(this)块中.但是有更好的方法吗?
To solve this problem I enclosed both the db interactions into a single synchronized(this) block. But is there a better way of doing this?
它更像是选择性同步,只有具有相同参数的线程才需要同步.选择性同步是否可能?
it is more like selective synchronization, only threads with same params need to by synchronized. Is selective synchronization possible?
推荐答案我想说,更好的方法是让数据库尽可能为您完成此操作.假设您要更新或插入的数据库行具有唯一的约束,那么我通常的方法是
I'd say the better way to do this would be to let the database do it for you if at all possible. Assuming the row on the database that you are wanting to either update or insert has a unique constraint on it, then my usual approach would be
- 无条件插入行
- 如果发生SQLException,请检查是否是由于插入错误时出现重复键造成的,如果是,请执行更新,否则重新抛出SQLException.
如果您可以将这些语句包装在数据库事务中,那么您就不必担心两个线程相互踩踏.
If you can wrap those statements in a database transaction, then you don't have to worry about two threads trampling on each other.
更多推荐
Java选择性同步
发布评论