-
동시성 문제를 해결하기 위해 동시에 요청을 받았을 때 어떻게 처리 되도록 할 지를 제어하는 것
💡동시성 문제 여러 개의 작업(스레드 또는 프로세스)이 동시에 실행되면서 공유 자원(예: 변수, 데이터 구조, 파일 등)에 접근하거나 수정하려고 할 때 발생하는 문제. 예)ID가 ‘1’ 인 사람에 대한 포인트 충전 요청이 동시에 들어왔을 경우
- 스프링은 기본적으로 멀티 스레드, 동기 방식으로 동작한다.
- Spring Boot가 실행될 때, 내장 Tomcat(Servlet Container)에서 ThreadPool을 생성한다.
- 사용자의 요청(HttpServletRequest) 하나 마다 Thread Pool에서 Thread를 하나씩 할당한다.
- 해당 Thread에서 Spring Boot에 작성한 Dispatcher Servlet을 거쳐 유저 요청을 처리한다.
- 작업을 모두 수행하고 나면 Thread는 Thread Pool로 반환된다.
-
ID가 ‘1’ 인 사람에 대한 포인트 충전 요청이 동시에 들어왔을 경우,
⇒ 실제로는 총 300 포인트 충전 요청이 들어왔지만 100 포인트 만 충전이 됐다.
-
동시성 문제가 생기기 않도록 하기 위해서 적절한 처리를 해주어야 한다. : 동시성 제어
-
synchronized 키워드를 사용해 해당 블럭의 액세스를 동기화할 수 있다. 즉, synchronized 가 선언된 블럭 에는 동시에 하나의 스레드만 접근할 수 있도록 하는 것이다.
⇒ 이것은 하나의 프로세스에서만 보장되는 특성으로 서버가 여러 대일 때는 동시성 문제에서 자유로울 수 없다.
- Syncronized는 jvm 수준에서 lock이 관리 되고 블럭과 메서드 범위에 동기화를 적용할 수 있지만, ReentrantLock은 명시적으로 lock과 unlock을 제공하여 조금 더 세밀하게 동기화를 제어할 수 있다고 한다.
- 또한 ReentrantLock은 생성 시에 설정을 통해 공
-
단순히 하나의 Lock을 생성해서 포인트 충전 메서드를 호출 할 때 lock을, 작업이 종료된 후에 unlock을 한다면,,, Synchronized와 다를 바가 없다.
-
아이디 별로 lock을 관리하면 동시성 문제를 해결하면서 다른 ID 간의 요청은 병렬로 처리 될 수 있다.
-
이 방법에서도 Lock을 관리하는 Map에 여러 Thread가 동시에 같은 Lock에 접근하면서 마찬가지로 동시성 문제인
ConcurrentModificationException이 발생할 수 있다.⇒ 이 때문에 Thread-safety한 Map인 ContcurrentHashMap을 사용해야 했다.
-




