Java ReentrantLock 클래스 - 명시적으로 잠금 획득

명시적으로 잠금 획득 – ReentrantLock 클래스

public void lock()
public void unlock()

synchronized 블록에 의한 동기화는 어플리케이션 개발자가 락의 획득/해제를 의식하지 않아도 되기 때문에 “암묵적인 락"이라고 한다. 반대로 메서드를 통해서 “명시적으로 락"을 걸거나 해제하고 싶은 경우가 있다. 이런 경우에는 ReentrantLock 클래스(java.util.concurrent.locks 패키지)를 이용한다.

ReentrantLock 클래스에서는 lock 메서드로 명시적으로 락을 건 후에는 unlock 메서드로 해제해줘야 한다.

다음은 synchronized 한정자 사용한 예제(increment 메서드)을 ReentrantLock 클래스에서 다시 작성한 것이다.

LockSample.java

package com.devkuma.basic.thread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockSample {
    private int count;
    private final Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        LockSample ls = new LockSample();
        ls.execute();
    }

    public void execute() {
        final int THREAD_MAX = 300000;
        Thread[] ts = new Thread[THREAD_MAX];
        for (int i = 0; i < THREAD_MAX; i++) {
            ts[i] = new Thread(new MyThread(this));
            ts[i].start();
        }
        for (int i = 0; i < THREAD_MAX; i++) {
            try {
                ts[i].join();
            } catch (InterruptedException e) {
                System.out.println(e);
            }
        }
        System.out.println(count);
    }

    public void increment() {
        lock.lock();
        try {
            this.count++;
        } finally {
            lock.unlock();
        }
    }

    private static class MyThread implements Runnable {
        private LockSample _counter;

        public MyThread(LockSample counter) {
            this._counter = counter;
        }

        @Override
        public void run() {
            _counter.increment();
        }
    }
}

실행 결과:

300000

ReentrantLock 클래스에서 lock 메서드를 사용을 하게 되면, 그 직후에 try 블록으로 감싸야 한다. 이는 처리 중에 예기치 않은 예외가 발생한 경우에도 finally 절에서 unlock 메서드가 호출되는 것을 보장하기 위해서 이다.




최종 수정 : 2022-09-24