참여 엔티티 추가 시 데드락 발생이전에 낙관적 락 방식을 사용하여 플로깅 참여하기 api 를 구현해 보았다.
플로깅 구인 게시판에 참여 인원을 카운트 하는 필드에 대해서 동시성 이슈가 발생하는 부분에 대한 해결법으로 낙관적 락을 사용하였다. 하지만 이 해결법 만으로는 주어진 문제를 완벽하게 해결하진 못했다.
참여 인원을 카운트 하는 것은 성공적 이었다.
하지만 궁극적으로 참여 인원 카운트 + 참여 인원 목록을 DB에 저장을 해야했다.
따라서 참여 를 관리하는 엔티티를 생성하여 연관관계를 걸어 두었으나, 참여하기 api 에 대해 테스트 해본 결과 데드락 문제가 발생하였다.
지난 이야기는 참여인원 카운트 관련 동시성 이슈 탐구 및 해결 를 확인 해보자.
아래 코드가 데드락이 발생하는 테스트 코드이다.
package mokindang.jubging.project_backend.recruitment_board.service;
import mokindang.jubging.project_backend.recruitment_board.domain.RecruitmentBoard;
import mokindang.jubging.project_backend.recruitment_board.repository.RecruitmentBoardRepository;
import mokindang.jubging.project_backend.recruitment_board.service.facade.OptimisticLockRecruitmentBoardResolver;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest
class RecruitmentBoardConcurrencyTest {
//...
@Test
@DisplayName("동시성 문제 - 7명이 동시에 요청한 경우 게시글 카운트가 8이됨")
void SuccessCountUp() throws InterruptedException {
int threadCount = 7;
ExecutorService executorService = Executors.newFixedThreadPool(32);
CountDownLatch latch = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
int memberId = i + 2;
executorService.submit(() -> {
try {
recruitmentBoardService.participate((long) memberId, 1L);
} catch (final Exception e) {
System.out.println(e.getMessage());
} finally {
latch.countDown(); // 카운트
}
});
}
latch.await();
RecruitmentBoard recruitmentBoard = recruitmentBoardRepository.findById(1L).get();
assertThat(recruitmentBoard.getParticipationCount().getCount()).isEqualTo(8);
}
}
//...
구현은 다음과 같이 하였다.