본문으로 바로가기
반응형


실행 어라운드 패턴(Execute around pattern)에 대한 두번째 예시 입니다.


먼저 1번글에서는 resource의 명시적인 해제시 해체할 수 있는 틀(try-catch-with-resource)를 만들어 넣고 내부에 인자로 실제 동작해야 할 구문을 넣는 형태를 얘기했었습니다.

이때 인자는 당연히 functional interface 입니다.


같은 방법으로 이번에는 lock을 사용하는 방법을 알아봅니다.

잠금(lock)의 관리

lock은 왜 써야 할까요?
저는 사실 synchronized만 쓴 터라 lock의 개념이 무척 궁금했더랍니다.
Java5부터 추가된 개념으로 동기화를 좀더 디테일?? 하게 관리하기 위해서 사용합니다.

예를 들면 하나의 함수 블럭을 넘어간다던가, 무작정 lock을 대기하는게 아니라 timeout을 건다든가..등등 세밀하게 조정할 수 있는거죠
lock의 내용이 궁금하시다면 잘 정리된 아래 블로그를 확인 하시면 됩니다.

lock을 사용하기 위해서는 명시적으로 lock과 unlock을 해야하고 따라서 try-catch를 써야만 안전합니다.

역시..
execute around pattern에 딱 맞는 조건이네요.



lock의 기본 동작 코드

일단 lock을 사용하기 위해서는 lock을 상속받아 구현하 ReentrantLock을 사용합니다.
public class Locking {
  Lock lock = new ReentrantLock(); //or mock
  
  protected void setLock(final Lock mock) {
    lock = mock;
  } 

  public void doOp1() {
    lock.lock();
    try {
      //...critical code...
    } finally {
      lock.unlock();
    }
  }
  //...


이건 doOp1() 함수에 lock을 걸고 푸는 코드가 다 들어있습니다.

요 기능만 같는 클래스로 분리해 보겠습니다.

public class Locker {
  public static void runLocked(Lock lock, Runnable block) {
    lock.lock();
	
    try {
      block.run();
    } finally {
      lock.unlock();
    }    
  }
}


이렇게 runLocked란 함수를 이용하면 호출 부분에서는 lock과 unlock을 pair를 신경쓰지 않고 사용이 가능합니다.

public void doOp2() {
	runLocked(lock, () -> {/*...critical code ... */});
}
  
public void doOp3() {
    runLocked(lock, () -> {/*...critical code ... */}); 
}
  
public void doOp4() {
    runLocked(lock, () -> {/*...critical code ... */});
}



반응형