简体   繁体   English

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

[英]Preventing Java web service from concurrent modification of record

I am running a Java web service inside Tomcat. 我在Tomcat中运行Java Web服务。

The service is consumed by several Rails applications which are supposed to coordinate concurrent modification but don't do a very good job. 该服务由多个Rails应用程序使用,这些应用程序应该协调并发修改,但做得不好。

There is only one service method of interest, which attempts to PUT a user record, but it does a lot of processing and can take a while. 感兴趣的服务方法只有一种,它试图插入用户记录,但是它会进行大量处理,并且可能需要一段时间。 It is entirely likely that more than one of these Rails applications will attempt to push in a change to the same user while a previous call is still being processed. 在仍在处理先前的呼叫的同时,这些Rails应用程序中有多个可能会尝试将更改推送给同一用户。

My understanding of Tomcat's one-thread-per-request is that I'm really dealing with a multithreading problem, but instead of synchronizing on the service object I want to synchronize somehow on the transient user id. 我对Tomcat的每个请求一个线程的理解是,我实际上正在处理多线程问题,但是我不想在服务对象上进行同步,而是想以某种方式在瞬态用户ID上进行同步。

I thought of using a Set to store currently-processed user ids, and then synchronizing on the collection's object. 我想到了使用Set存储当前处理的用户ID,然后在集合的对象上进行同步。 The first to be able to add the user id to the collection gets to process, while the one that discovers the userid already in the collection returns with, say, a 409 Conflict error. 第一个能够将用户ID添加到集合中的对象将要处理,而发现已经在集合中的用户ID的对象将返回,例如409冲突错误。

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()) {
    }

}

Does this sound feasible? 这听起来可行吗? I haven't found anything built into Tomcat or Spring MVC that would automatically handle this kind of behavior, but is there already a built-in solution of which I am not aware? 我还没有发现可以自动处理这种行为的任何内置在Tomcat或Spring MVC中的东西,但是已经有了我不知道的内置解决方案吗?

I think that the solution you proposed should work, as long as you have a single instance of the webapp running (as pointed out by Erwin in the comments). 我认为,只要您有一个运行的Web应用程序实例(如Erwin在评论中指出的那样),您提出的解决方案就应该起作用。 I don't know of any built-in solution doing exactly that. 我不知道有任何内置解决方案可以做到这一点。

To make the code easier to read, you could also use a synchronized set and get rid of the two synchronized statements: 为了使代码更易于阅读,您还可以使用同步集并摆脱两个synchronized语句:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM