JAVA
람다 표현식을 사용한 잠금(lock) 관리
.노을.
2017. 3. 17. 18:52
반응형
잠금(lock)은 병렬로 실행되는 자바 애플리케이션에서 중요한 역할 을 한다.
synchronized 는 상호 배재(mutual exclusion)를 제공하기 위해 사용되어온 오래된 키워드이지만, 두가지 단점을 가지고 있다.
- 메서드가 호출되는 시간을 제어하기 어렵다. - 이것은 데드록(deadlock) 과 라이브록(livelock) 이 발생할 가능성을 증가시킨다.
- 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 |
위의 코드처럼 람다를 사용할 경우 매우 쉽고 간결하게 문제를 해결할 수 있다.
반응형