防止Java Web服务同时修改记录

时间:2014-09-06 02:30:05

标签: java multithreading spring tomcat

我正在Tomcat中运行Java Web服务。

该服务由多个Rails应用程序使用,这些应用程序应该协调并发修改但不能做得很好。

只有一种感兴趣的服务方法,它尝试PUT一个用户记录,但它做了很多处理,可能需要一段时间。完全可能的是,这些Rails应用程序中的多个应用程序会在前一个呼叫仍在处理时尝试将更改推送到同一个用户。

我对Tomcat的每个请求的一个线程的理解是我真正处理多线程问题,但是我不想在服务对象上进行同步,而是想在瞬态用户id上以某种方式进行同步

我想过使用Set来存储当前处理的用户ID,然后同步集合的对象。能够将用户ID添加到集合的第一个进程处理,而发现已经在集合中的用户ID的那个返回,例如,409 Conflict错误。

Set<String> activeUserIds = new HashSet<String>();

// annotations, mappings, etc.
public ResponseEntity<String> putUser(User user) {

    boolean canProcess;
    synchoronize(activeUserIds) {
        canProcess = activeUserIds.add(user.getId()) {
    }

    if (!canProcess) {
        return new ResponseEntity<String>("user already being modified", Status.CONFLICT);
    }

    // perform service activity

    synchoronize(activeUserIds) {
        activeUserIds.remove(user.getId()) {
    }

}

这听起来可行吗?我还没有发现内置在Tomcat或Spring MVC中的任何内容会自动处理这种行为,但是我已经有一个我不知道的内置解决方案了吗?

1 个答案:

答案 0 :(得分:0)

我认为你提出的解决方案应该有效,只要你运行一个webapp实例(正如Erwin在评论中指出的那样)。我不知道任何内置的解决方案正是如此。

为了使代码更易于阅读,您还可以使用同步集并删除两个synchronized语句:

Set<String> activeUserIds = Collections.synchronizedSet(new HashSet<String>());