Контроллер Spring с синхронизированным блоком, похоже, блокирует весь метод, а не только блок кода

#java #spring #spring-boot #spring-mvc #synchronized

#java #весна #spring-boot #spring-mvc #синхронизированный

Вопрос:

 @Slf4j
@RestController
public class DemoController {
    @GetMapping
    public String testStr(String str) {
        String key = UUID.randomUUID().toString();
        log.info("testStr start {} {}", str, key);
        synchronized (str.intern()) {
            log.info("testStr in {} {}", str, key);
            Thread.sleep(5000);
        }
        log.info("testStr end {} {}", str, key);
        return str;
    }
}
 

Когда я вызываю с двумя запросами ?str=aaa , журнал выглядит так:

  testStr start aaa 3bbb03e3-84d9-4816-b275-de59657bd810
 testStr in aaa 3bbb03e3-84d9-4816-b275-de59657bd810
... after 5 sec
 testStr end aaa 3bbb03e3-84d9-4816-b275-de59657bd810
 testStr start aaa b4f07a65-e37e-4471-be79-877a8d529f04
 testStr in aaa b4f07a65-e37e-4471-be79-877a8d529f04
... after 5 sec
 testStr end aaa b4f07a65-e37e-4471-be79-877a8d529f04
 

Но я думаю, что это должно быть

  testStr start aaa 3bbb03e3-84d9-4816-b275-de59657bd810
 testStr in aaa 3bbb03e3-84d9-4816-b275-de59657bd810
 testStr start aaa b4f07a65-e37e-4471-be79-877a8d529f04
... after 5sec
 testStr in aaa b4f07a65-e37e-4471-be79-877a8d529f04
 testStr end aaa 3bbb03e3-84d9-4816-b275-de59657bd810
... after 5 sec
 testStr end aaa b4f07a65-e37e-4471-be79-877a8d529f04
 

Другая часть: журнал testStr start... должен регистрироваться до 5 секунд.

Я что-то пропустил?

Кстати, я тестирую этот код с помощью простого main без spring, тогда все работает так, как ожидалось.

основной код

 public static void main(String[] args) {
        DemoController demoController = new DemoController();
        new Thread(()->{
            String result = demoController.testStr("aaa");
            log.info("result1 {}", result);
        }).start();
        new Thread(()->{
            String result = demoController.testStr("aaa");
            log.info("result2 {}", result);
        }).start();
    }
 

Комментарии:

1. То есть вы по сути хотите сказать, что java не знает, как синхронизировать? Поскольку это не имеет ничего общего ни с Spring, ни с Spring Boot, но как синхронизация применяется JVM.

2. Извините, но я не понимаю, о чем вы говорите. Если это проблема с JVM, почему я получил другой результат при запуске с чистым main?

3. Main однопоточный, это несколько потоков. Syncronized — это функция jvm, и то, как и что это блокирует, зависит от jvm, а не от spring.

4. Мой основной — это тоже несколько потоков, я обновляю свой вопрос: добавить основной класс. Пожалуйста, проверьте еще раз.

5. Если вы попробуете один из ваших 2 запросов на вкладке «инкогнито», а другой — на вкладке «Обычный», вы получите искомый результат.