본문 바로가기

dev/자바

Java thread lock synchronized

자바 멀티 스레드 환경에서 동시에 접근하는 자원이 있는 경우 동기화 처리가 필요합니다.

 

예를 들어 은행 계좌 이체나 티켓 예매 로직 같은 경우 동기화가 적용되어야 합니다.

 

Ticket.java

 

위의 Ticket.java의 reserveTicket 메소드는 Lock 객체를 통해 주어진 티켓 수만큼 예매하고 있습니다.(22 ~ 35라인)

 

Lock 객체 lock 메소드와 unlock 메소드 사이에 있는 코드는 동기화 처리되어 있어서

 

남아있는 티켓 수가 0보다 큰 경우 예매가 가능하고 0보다 작으면 예매가 되지 않고 있습니다.

 

lock.lock()은 잠금을 설정하고, lock.unlock()은 잠금을 해제하고 있습니다.

 

finally 블럭에 lock.unlock() 한 이유는 예외 발생 여부와 상관없이 잠금을 해제하기 위해서입니다.

 

User.java

 

User.java는 스레드를 구현하여 티켓을 예매하고 있습니다.

 

테스트 코드

 

테스트 코드에서 Ticket 객체를 빌더로 생성하는데

 

티켓 개수는 10개, 잠금을 관리하는 lock은 ReentrantLock 객체로 생성하고 있습니다.

 

ReentrantLock의 생성자 boolean 파라미터는 공정성을 나타내는 것으로 true면

 

오래 기다린 스레드에게 lock을 제공하고 있습니다.(11 ~ 14라인)

 

스레드를 티켓 개수보다 1개 많은 11개를 생성시켜 실행하면 다음과 같은 결과를 확인할 수 있습니다.

 

테스트 코드 실행 결과

 

테스트 코드를 실행하면 11개의 스레드 중 10개 스레드가 안전하게 티켓 예매를 확인할 수 있습니다.

 

나머지 1개 스레드는 남은 티켓이 없기 때문에 예약을 할 수 없습니다.

 

Ticket.java

 

Lock 외에 synchronized를 사용해서 동기화를 처리할 수 있습니다.

 

잠금을 설정하려는 메소드에 synchronized 추가하면 동기화가 적용됩니다.

 

테스트 코드 실행 결과

 

마찬가지로 테스트 코드를 실행하면 앞의 결과와 동일하게 출력되는 것을 확인할 수 있습니다.

 

ReentrantLock을 사용하면 잠금을 정교하게 설정할 수 있고 스레드에 공정성을 부여할 수 있지만

 

unlock 메소드를 잠금을 직접 해제해야 되는 단점이 있습니다.

 

synchronized를 사용하면 간단하게 동기화 처리할 수 있지만 정교하게 할 수 없는 단점이 있습니다.

 

상황에 맞게  ReentrantLock과 synchronized를 사용하면 좋을 것 같습니다.

'dev > 자바' 카테고리의 다른 글

Java Pattern 정규표현식  (0) 2024.05.03
JDK 11 FileReader Encoding  (0) 2024.04.22
Java List Stream  (0) 2023.08.29
Comparator&Comparable 인터페이스  (0) 2023.06.20
csv parsing lambda stream  (0) 2023.06.08