Is Spring MVC download controller multi-threaded?

I am new to Spring MVC and I have not found anything in this document. Say I have a controller / accounts that accept POST requests to create an account. Two requests arrive (almost) at the same time with the same account identifier. ASFAIK dispatcherServlet manages requests.

Is the second request queued before the first completion? Or do two threads simultaneously work with two requests?

UPDATE: Check out the official Spring Tutorial: Creating a REST Service . There is a controller with the add method:

 @RequestMapping(method = RequestMethod.POST) ResponseEntity<?> add(@PathVariable String userId, @RequestBody Bookmark input) { this.validateUser(userId); return this.accountRepository .findByUsername(userId) .map(account -> { Bookmark result = bookmarkRepository.save(new Bookmark(account, input.uri, input.description)); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setLocation(ServletUriComponentsBuilder .fromCurrentRequest().path("/{id}") .buildAndExpand(result.getId()).toUri()); return new ResponseEntity<>(null, httpHeaders, HttpStatus.CREATED); }).get(); } 

Controllers are just beans, by default they are solid. When two simultaneous requests are received, the same controller instance is used by two threads. Imagine that the 1st thread has already saved a new bookmark and completed

 httpHeaders.setLocation(ServletUriComponentsBuilder .fromCurrentRequest().path("/{id}") .buildAndExpand(result.getId()).toUri()); 

Meanwhile, the just completed 2nd stream

 Bookmark result = bookmarkRepository.save(new Bookmark(account, input.uri, input.description)); 

In this case, the first thread will return result.getId()).toUri() , which is created by the second thread.

Is this the right workflow and is this controller safe?

+3
source share
3 answers

With all structures of this type, we can safely assume that the controller methods will be processed simultaneously (i.e., in several parallel threads). In addition, this is a serious performance hit to do it in any other way (yes, there are frameworks developed in a completely different way than at the initial stage, but we are not talking about them now).

Spring itself does not know that part of the account id of the URL somehow synchronizes it. If it synchronizes at the URL level, this will result in poor performance. You can always implement this logic yourself, for example, by synchronizing on the object with the scope of the session on which this controller method works (or making the entire controller control session as Lev answers ). This will then serialize calls only to this user (this HTTP session). You may have a global shared lock if you want to synchronize between all users, but this is a really bad idea for the reasons mentioned above.

Instead, create an application so that all controllers are completely stateless and make the methods either idempotent, if possible, or have the correct logic for checking preconditions. If the method is written to the database, you can implement an optimization strategy with optimization. Hibernate already has this feature, and some DB / drivers also have this, so see what applies to your case.

UPDATE

In the presented example, both streams save an instance (I assume that save means insert / update as needed), and the returned object is the result of the current save operation, so there is no strange behavior between the streams. This suggests that persistence is transactional with a reasonable level of transaction isolation (any other assumption would be quite unusual). Be that as it may, the second stream will simply overwrite the values ​​recorded by the first, but this is probably what you expect. However, you only read the identifier on the next line, and that apparently never changes, so in any case, the creation of the URL seems unaffected by concurrency.

+2
source

The solution to the problem may be as follows:

  • Annotate controller with @Scope ("request") or @Scope ("session")
  • Move a private variable to one of the methods or save it in a session or model

I got it from there

+2
source

Most servlets run a separate thread for each incoming request, and Spring is no exception. You must ensure that generic beans are thread safe. Otherwise, Spring will take care of the rest.

+1
source

Source: https://habr.com/ru/post/1479073/


All Articles