ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 람다 표현식을 사용한 잠금(lock) 관리
    JAVA 2017. 3. 17. 18:52
    반응형

    잠금(lock)은 병렬로 실행되는 자바 애플리케이션에서 중요한 역할 을 한다. 

    synchronized 는 상호 배재(mutual exclusion)를 제공하기 위해 사용되어온 오래된 키워드이지만, 두가지 단점을 가지고 있다. 

    1. 메서드가 호출되는 시간을 제어하기 어렵다. - 이것은 데드록(deadlock) 과 라이브록(livelock) 이 발생할 가능성을 증가시킨다.
    2. synchronized 를 실제 적용하는 것이 어렵다. - 코드가 thread safety에 있는지를 체크하기 위한 unit test를 어렵게 만든다. 

    synchronized 의 문제를 해결하기 위해 자바5 에서 Lock 인터페이스와 ReentrantLock 등의 구현이 추가 되었다. Lock 인터페이스는 lock, unlock, check 등에 대한 더 향상된 인터페이스를 제공하며 특정 시간 안에 잠금(Lock)을 얻지 못하면 타임 아웃되도록 한다.

    [Lock 인터페이스를 사용한 코드]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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();
            }
        }
     
        // ...
     
    }
    cs


    Lock 을 상요한 doOp2() 를 추가해야 한다면, lock을 설정하지 않거나, 해지하지 않는 등의 오류가 쉽게 발생 할 수 있으며 유지 보수도 어렵다.

    [람다 표현식을 사용한 코드]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class Locker {
        public static void runLocked(Lock lock, Runnable block) {
            lock.lock();
            try {
                block.run();
            } finally {
                lock.unlock();
            }
        }
    }
    cs

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class Locking {
        Lock lock = new ReentrantLock(); // or mock
     
        protected void setLock(final Lock mock) {
            lock = mock;
        }
     
        public void doOp1() {
            runLocked(lock, () -> { /* ... critical code ... */});
        }
     
        public void doOp2() {
            runLocked(lock, () -> { /* ... critical code ... */});
        }
     
        public void doOp3() {
            runLocked(lock, () -> { /* ... critical code ... */});
        }
     
        // ...
     
    }
    cs

    위의 코드처럼 람다를 사용할 경우 매우 쉽고 간결하게 문제를 해결할 수 있다.


    반응형

    댓글

Designed by Tistory.