티스토리 뷰

Java/Java

<Java> ReentrantLock이란?

면목동인간 2024. 10. 26. 15:25

ReentrantLock이란?

 sychronized의 BLOCKED 상태, 무한대기 등 임계 영역 관리 한계를 극복하기 위해 자바에서 제공한 클래스이다. 아래 예제를 통해 알아보았다.

 

<Java> Thread sychronized이란?

sychronized이란? java의 키워드이며 메서드에 선언한다. 선언된 메서드는 멀티스레드 상황에서 하나의 스레드만 실행할 수 있다. 아래 예제를 통해 알아보았다. sychronized 사용X 예제Main.javapublic clas

oniic.tistory.com

sychronized의 단점

  • BLOCKED 상태의 스레드는 락일 풀릴 때까지 무한 대기한다. 인터럽트 X.
  • 락이 돌아오더라도 어떤 스레드가 락을 획득하는지 알 수 없다. (공정성 문제)

ReentrantLock 예제

 밑에 예제는 위의 sychronized 포스팅의 예제를 활용하여 ReentrantLock로 바꿨다.

 

Main.java

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        Runnable task = new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 10000; i++) {
                    counter.increment();
                }
            }
        };
        Thread thread1 = new Thread(task);
        Thread thread2 = new Thread(task);
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println("결과: " + counter.getCount());
    }
    static class Counter {
        private int count = 0;
        // ReentrantLock 추가
        private final Lock lock = new ReentrantLock();
        
        public void increment() {
            // ReentrantLock에서 락 획득 그렇지 않은 스레드는 대기 큐에 들어감             
            lock.lock();
            try{
                count = count + 1;
            } finally {
                // ReentrantLock에 락 반납. 대기 큐에 있는 스레드는 락 획득.             
                lock.unlock();
            }
        }
        public int getCount() {
            return count;
        }
    }
}

실행 결과

결과: 20000

 위의 실행 결과를 보면 앞선 sychronized를 사용했던 것과 마찬가지로 같은 결과를 출력했다. 하지만 내부적으로는 sychronized와 많은 차이점이 있는데 아래 그림을 통해 나타내었다.

 위의 그림은 실행 결과를 순서대로 간략히 표현하였다. 한마디로 ReentrantLock 클래스는 내부에 락이 있는데 스레드 1이 lock()을 실행하여 락을 획득하면 다른 스레드들은 락을 획득할 때까지 대기 큐에 대기하며(WAITING 상태로) 스레드 1이 unlock()을 실행하여 락을 반납하면 대기하고 있던 다른 스레드가 락을 획득 후 실행한다. (※반드시 unlock을 실행해야 한다. 그렇지 않으면 다른 스레드들은 무한 대기 중이 된다. 락을 반납하지 않았기 때문.) 

 

공정 모드 VS 비공정 모드

ReentrantLock은 생성자에 true,false(기본 값)을 전달하여 공정 모드와 비공정 모드를 사용할 수 있다. 두 가지를 비교하여 원하는 대로 사용하면 된다.

 

공정 모드

 ReentrantLock 생성자에 true를 전달하면 된다. 락을 요청한 순서대로 스레드가 락을 획득할 수 있게 한다. 단 성능이 저하될 수 있다.

  • 공정성 보장: 대기 큐에서 먼저 대기한 스레드가 락을 먼저 획득한다.
  • 기아 현상 방지: 모든 스레드가 언젠가 락을 획득할 수 있게 보장된다.
  • 성능 저하: 락을 획득하는 속도가 느려질 수 있다.

비공정 모드

 ReentrantLock 의 기본 모드이다. 락을 풀었을 때, 대기 중인 스레드 중 아무나 락을 획득할 수 있다. 이는 락을 빨리 획득할 수 있지만, 특정 스레드가 장기간 락을 획득하지 못할 가능성도 있다.

  • 성능 우선: 락을 획득하는 속도가 빠르다.
  • 선점 가능: 새로운 스레드가 기존 대기 스레드보다 먼저 락을 획득할 수 있다.
  • 기아 현상 가능성: 특정 스레드가 계속해서 락을 획득하지 못할 수 있다.

주요 메서드 정리

  • lock(): 락을 획득한다. 한 스레드가 락을 획득하고 있을 때 다른 스레드가 락을 획득하려고 하면 획득하지 못하고 대기 큐에 들어간다. (WAITING 상태로 대기)
  • unlock(): 락을 반납한다. 락을 반납하면 대기 큐에 있던 스레드가 락을 획득 후 실행한다. (WAITING -> RUNNABLE)
  • tryLock(): 락을 획득 여부에 따라 true,false를 반납한다. 락을 획득 중인 스레드가 있을 때 다른 스레드가 획득하려고 하면 false를 반납하고 대기 큐에 들어가지 않는다.
  • tryLock(long time, TimeUnit unit): 주어진 시간 동안 락 획득을 시도한다. 시간 안에 락을 획득하면 true를 반납하고 그렇지 않으면 false를 반납한다. 만약 대기 중 인터럽트가 발생하면 InterruptedException이 발생하고 락을 획득하지 못한다. (TIME_WAITING 상태로 대기)

정리

 ReentrantLock은 앞선 sychronized의 BLOCKED, 무한 대기, 공정성 등 단점을 해결해주는 클래스이다. 또한 공정 비공정 모드를 제공하므로 원하는 것을 선택하여 사용하면 된다.

 


본 포스팅은 “김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성/인프런”를 학습한 내용을 정리한 것

'Java > Java' 카테고리의 다른 글

<Java> 버퍼 이란?  (0) 2025.03.04
<Java> Object 객체의 wait(), notify(), notifyAll() 메서드란?  (1) 2025.01.25
<Java> sychronized이란?  (1) 2024.10.22
<Java> volatile이란?  (0) 2024.10.18
<Java> Thread join() 메서드란?  (3) 2024.10.16
댓글
최근에 올라온 글
«   2026/03   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함
Total
Today
Yesterday