반응형

 

https://www.youtube.com/watch?v=ahBC69_iyk4

 

ReentrantLock란?

동기화된 메소드와 문장을 사용하여 액세스 할 수 있는 암시적인 모니터 잠금 기능과 같은 기본적인 동작과 의미를 가진 Reentrant 상호 간의 상호 배제된 상호 배제 잠금 기능을 의미한다.

이는 마치 뮤텍스와 많이 흡사한 모습을 띄고 있다.

 

즉, 상호 배타적 락이며 기본적으로 synchronized 키워드를 이용한 암시적인 모니터와 같이 동작한다.

 

동기화에는 아래와 같은 내용들이 있는데 이중 ReentrantLock는 Mutex라고 생각하면 쉽다.

방법 설명

 임계영역(critical section)

 공유 자원에 대해 단 하나의 스레드만 접근하도록 한다.

 (하나의 프로세스에 속한 스레드만 가능하다) 

 뮤텍스 (mutex)

 공유 자원에 대해 단 하나의 스레드만 접근하도록 한다.

 (서로 다른 프로세스에 속한 스레드도 가능) 

 이벤트 (event) 

 특정한 사건의 발생을 다른 스레드에게 알린다. 

 세마포어 (Semaphore)

 한정된 개수의 자원을 여러 스레드가 사용하려고 할 때 접근을 제한한다.  

 대기 가능 타이머 (waitable timer)

 특정 시간이 되면 대기중이던 스레드를 깨운다.

 

package CountDownLatch;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

public class CountDownLatchTest {
	public static void main(String[] args) {
		AtomicInteger ordinal = new AtomicInteger(0);
		final CountDownLatch latch = new CountDownLatch(10);
	
		for (int i = 0; i < 10; ++ i)
		{
			Thread thread = new Thread() {
		  	@Override
		  	public void run() {
		  	  synchronized(ordinal) {
		  	  ordinal.getAndIncrement();
		  	  System.out.println("Waiting " + ordinal.get() + " thread");
			  latch.countDown();
		  	  }
		  	  try {
		  	  	latch.await();
		  	  } catch (InterruptedException e) {
				e.printStackTrace();
			  }
		  	}
		  };
		  thread.start();
		}
	}
}

보통은 동기화를 다음과 같이 synchronized로 한다.

 

하지만 ReentrantLock의 장점은 mutex처럼 시작과 끝의 lock, unlock를 명확히 할 수 있다는 장점이 있다.

 

 

ReentrantLock 사용 방법

 

package CountDownLatch;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;

class CountDownLatchTest{
	public static void main(String[] args) {
		ReentrantLock reentrantLock = new ReentrantLock();
		AtomicInteger ordinal = new AtomicInteger(0);
		
		for(int i = 0 ; i < 20; i ++) {
			reentrantLock.lock();
			Thread thread = new Thread() {
				@Override
				public void run() {
					for(int i = 0 ; i < 1000000; i ++) {
						ordinal.getAndIncrement();
					}
				}
			};
			thread.start();
			reentrantLock.unlock();

			try {
				thread.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println(ordinal.get());
	}
}

이와같이 lock, unlock를 통해 뮤텍스 처럼 동일하게 사용 할 수 있는 장점이 있다.

 

https://www.crocus.co.kr/search/%EB%AE%A4%ED%85%8D%EC%8A%A4

 

'뮤텍스'의 검색결과

다양한 프로그래밍 정보를 제공

www.crocus.co.kr

기존 스레드를 동기화 하기위해 사용하던 3개의 주요 메소드 : wait, notify, notifyAll

ReentrantLock에서는 await(), signal(), signalAll() 메소드와 같다. 

 

하지만 이때는 Condition 객체를 이용하여 락을 관리해야한다.(모든 것은 뮤텍스와 동일함을 알 수 있다.)

 

import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
 
class SomeClass {
    private final ReentrantLock locker = new ReentrantLock();
    private final Condition lockerCondition = locker.newCondition();
    public void SomeMethod () {
        locker.lock();  // 쓰레드에 락을 겁니다.(동기화의 시작)
        try {
            동기화내용들...
            lockerCondition.await();        //기존의 동기화에서 wait();
            lockerCondition.signal();       //기존의 동기화에서 notify();
            lockerCondition.signalAll();    //기존의 동기화에서 notifyAll();
        } catch (어떤예외들) {
            해당예외처리...
        } finally {
            locker.unlock();    // 쓰레드의 락을 풉니다.(동기화 끝지점)
        }
    }
}

https://eskeptor.tistory.com/83

반응형