Spring 동시성 문제

정명진·2022년 5월 30일
0

Spring Advanced 수강 정리글 입니다.

일반적인 Thread 사용시 여러 사용자가 동시 요청하면 동시성 문제가 생길 수 있다. 동시성 문제가 발생하면 꽤나 골치아프게 됨.. 특히 스프링은 Singleton 방식이기 때문에 치명적이다.
실제로 실습중 요청을 여러번 보냈더니 아래와 같이 로그가 수상하게 찍힘.


2022-05-30 13:17:52.687  INFO 46437 --- [nio-8080-exec-4] s.datajpa.trace.logtrace.FieldLogTrace   : [9051a058] OrderController.request()
2022-05-30 13:17:52.687  INFO 46437 --- [nio-8080-exec-4] s.datajpa.trace.logtrace.FieldLogTrace   : [9051a058] |-->OrderService.orderItem()
2022-05-30 13:17:52.687  INFO 46437 --- [nio-8080-exec-4] s.datajpa.trace.logtrace.FieldLogTrace   : [9051a058] |  |-->OrderRepository.save()
2022-05-30 13:17:53.195  INFO 46437 --- [nio-8080-exec-5] s.datajpa.trace.logtrace.FieldLogTrace   : [9051a058] |  |  |-->OrderController.request()
2022-05-30 13:17:53.196  INFO 46437 --- [nio-8080-exec-5] s.datajpa.trace.logtrace.FieldLogTrace   : [9051a058] |  |  |  |-->OrderService.orderItem()
2022-05-30 13:17:53.196  INFO 46437 --- [nio-8080-exec-5] s.datajpa.trace.logtrace.FieldLogTrace   : [9051a058] |  |  |  |  |-->OrderRepository.save()
2022-05-30 13:17:53.692  INFO 46437 --- [nio-8080-exec-4] s.datajpa.trace.logtrace.FieldLogTrace   : [9051a058] |  |<--OrderRepository.save() time=1005ms
2022-05-30 13:17:53.693  INFO 46437 --- [nio-8080-exec-4] s.datajpa.trace.logtrace.FieldLogTrace   : [9051a058] |<--OrderService.orderItem() time=1006ms
2022-05-30 13:17:53.693  INFO 46437 --- [nio-8080-exec-4] s.datajpa.trace.logtrace.FieldLogTrace   : [9051a058] OrderController.request() time=1006ms
2022-05-30 13:17:54.200  INFO 46437 --- [nio-8080-exec-5] s.datajpa.trace.logtrace.FieldLogTrace   : [9051a058] |  |  |  |  |<--OrderRepository.save() time=1004ms
2022-05-30 13:17:54.201  INFO 46437 --- [nio-8080-exec-5] s.datajpa.trace.logtrace.FieldLogTrace   : [9051a058] |  |  |  |<--OrderService.orderItem() time=1005ms
2022-05-30 13:17:54.201  INFO 46437 --- [nio-8080-exec-5] s.datajpa.trace.logtrace.FieldLogTrace   : [9051a058] |  |  |<--OrderController.request() time=1006ms

스프링에서 동시성을 해결하는 방법은 무엇일까?

답은 바로 ThreadLocal을 사용하는 것!
ThreadLocal은 각각의 지정공간에 값 세팅이 가능하다. 따라서 소유자가 구별된다는 소리. 즉 동시성 문제에서 자유롭게 된다.

2022-05-30 13:47:07.109  INFO 67935 --- [nio-8080-exec-1] s.d.trace.logtrace.ThreadLocalLogTrace   : [165eb75e] OrderController.request()
2022-05-30 13:47:07.109  INFO 67935 --- [nio-8080-exec-1] s.d.trace.logtrace.ThreadLocalLogTrace   : [165eb75e] |-->OrderService.orderItem()
2022-05-30 13:47:07.113  INFO 67935 --- [nio-8080-exec-1] s.d.trace.logtrace.ThreadLocalLogTrace   : [165eb75e] |  |-->OrderRepository.save()
2022-05-30 13:47:07.746  INFO 67935 --- [nio-8080-exec-3] s.d.trace.logtrace.ThreadLocalLogTrace   : [60f862c2] OrderController.request()
2022-05-30 13:47:07.746  INFO 67935 --- [nio-8080-exec-3] s.d.trace.logtrace.ThreadLocalLogTrace   : [60f862c2] |-->OrderService.orderItem()
2022-05-30 13:47:07.747  INFO 67935 --- [nio-8080-exec-3] s.d.trace.logtrace.ThreadLocalLogTrace   : [60f862c2] |  |-->OrderRepository.save()
2022-05-30 13:47:08.114  INFO 67935 --- [nio-8080-exec-1] s.d.trace.logtrace.ThreadLocalLogTrace   : [165eb75e] |  |<--OrderRepository.save() time=1000ms
2022-05-30 13:47:08.114  INFO 67935 --- [nio-8080-exec-1] s.d.trace.logtrace.ThreadLocalLogTrace   : [165eb75e] |<--OrderService.orderItem() time=1005ms
2022-05-30 13:47:08.114  INFO 67935 --- [nio-8080-exec-1] s.d.trace.logtrace.ThreadLocalLogTrace   : [165eb75e] OrderController.request() time=1005ms
2022-05-30 13:47:08.747  INFO 67935 --- [nio-8080-exec-3] s.d.trace.logtrace.ThreadLocalLogTrace   : [60f862c2] |  |<--OrderRepository.save() time=1000ms
2022-05-30 13:47:08.749  INFO 67935 --- [nio-8080-exec-3] s.d.trace.logtrace.ThreadLocalLogTrace   : [60f862c2] |<--OrderService.orderItem() time=1003ms
2022-05-30 13:47:08.749  INFO 67935 --- [nio-8080-exec-3] s.d.trace.logtrace.ThreadLocalLogTrace   : [60f862c2] OrderController.request() time=1003ms

Thread Id도 구분되고 정상적으로 로그가 출력됨.


ThreadLocal<T> threadLocal = new ThreadLocal<>();
T value;
threadLocal.set(value);
threadLocal.get();
threadLocal.remove();
profile
개발자로 입사했지만 정체성을 잃어가는중... 다시 준비 시작이다..

0개의 댓글