代码之家  ›  专栏  ›  技术社区  ›  Neo

对@putmapping并发请求的spring@service线程安全问题

  •  1
  • Neo  · 技术社区  · 6 年前

    我们有一个控制器,如下所示:

    @RestController()
    public class TestController {
    
      @Autowired
      TestService testService;
    
      ....
    
      // Update request
      @PutMapping("/update")
      public ResponseEntity<Sample> updateApi(@PathVariable(value = "id") Long id,
          @Valid @RequestBody Sample sampleDetails) {
        return new ResponseEntity<Sample>(testService.updateSample(id, sampleDetails), HttpStatus.OK);
      }
    
    ....
    

    服务类(依赖于JPA存储库)如下:

    @Service
    public class TestService {
    
      @Autowired
      TestRepository testRepository;
    
      // update sample
      public Api updateSample(long sampleId, Sample details) {
    
        // Get object to be updated
        Sample sample = apiRepository.findById(sampleId);
    
        // Update required fields
        sample.setName(details.getName());
        sample.setBody(details.getBody());
        return apiRepository.save(api);
      }
    
    1. 在上面的服务(testservice)中,setname和setbody方法调用JPA存储库:执行这些步骤是否保持状态(即非无状态),并且在处理并发请求时可能导致问题。或者我们是否需要将此服务的范围(或者服务中的updateSample方法)设置为“Web感知的Spring应用程序上下文”
    2. 与第1点类似,这一行:“sample=apiprepository.findbyid(sampleid);”,这一行是线程安全的还是在处理并发请求时可能导致问题。
    2 回复  |  直到 6 年前
        1
  •  1
  •   Vlad Bochenin Rom4in    6 年前

    您的代码中没有线程之间共享的任何状态。 除非您的存储库不返回一些可以在几个线程之间共享的缓存对象。

    如果存储库对 findById 方法调用并创建新的 Sample 对象,对象仅对当前线程可见。 Why are local variables thread safe in Java

    但你有 Transaction Isolation 问题是因为服务的方法 updateSample 执行超出事务范围,数据库中的数据可以由另一个线程或进程在 芬迪比德 save .

        2
  •  1
  •   Jonathan JOhx    6 年前

    好吧,让我们深入了解如何使用您的示例:

    1. 通常是应用服务器 (tomcat, undertown, jetty, others) 管理一个线程池,每个请求都由一个安全的线程处理。
    2. 当用户请求进入时 Controller ,将创建一个线程安全机制,并且在控制器返回响应以完成请求之前保持自身。所以请求在 Service 和电话 Repository 将在线程安全中。
    3. 您可以使用一些压力工具通过并发请求来测试这个简单的代码。 (Gatling, JMeter, or other) 而且,由于应用程序服务器创建了一个线程池以管理并发处理的线程安全性,因此它们使用的所有共享资源(服务、存储库等)都必须确保线程安全,因此您不会有任何问题。