코딩딩/Java

ReentrantLock

전낙타 2024. 9. 4. 17:35

1. 학습 목표

  • Synchronized를 ReentrantLock으로 최적화해보자

2. 학습 내용

ReentrantLock

Synchronized 와 ReentrantLock 의 가장 큰 차이점은 Lock을 걸어주고 풀어주는 시점을 직접 조작함으로써 좀더 세밀한 조작이 가능하다는 점이다.

Synchronized 은 자동 잠금해제에 속하고, ReentrantLock 은 명시적 잠금해제가 필요하다.

ReentrantLock 은 tryLock() 같은 다양한 메서드를 지원하는데 이는 고성능의 동시성제어가 필요한 상황에서 더 유리하게 작용한다.

그런 저번에 작성한 코드를 ReentrantLock으로 최적화해보자.

		lock.unlock();
		try {
			// 과목의 현재 수강신청 인원 카운터 가져오기 (없으면 새로 생성)
			currentCount = subjectCurrentCount.computeIfAbsent(
				String.valueOf(subject.getSubjectName()), k -> new AtomicInteger(subject.getRegistration().size()));

			// 수강신청 인원 증가 및 최대 인원 체크
			if (currentCount.incrementAndGet() > subject.getMaximumStudent()) {
				currentCount.decrementAndGet(); // 초과 시 다시 감소
				return new RegistrationResult(false, "수강 신청 인원이 초과되었습니다.");
			}
		} finally {
			lock.unlock();
		}

		try {
			// 수강신청 정보 저장
			Registration registration = Registration.of(member, subject);
			registrationRepository.save(registration);
			return new RegistrationResult(true, "수강 신청이 완료되었습니다.");
		} catch (Exception e) {
			lock.lock();
			try {
				currentCount.decrementAndGet(); // 저장 실패 시 인원 감소
			} finally {
				lock.unlock();
			}
			throw e;
		}

솔직히 최적화랄것도 없다.

지금 로직은 아주 간단한 로직이여서 다음과 같이 대처가 가능하지만 Task의 우선순위에 따라 잠금을 획득하는 방법또한 구현할 수 있다.

실질적으로 동기화가 필요한 로직을 작성할 때 한번 도전해봐야겠다.