1) Lock과 Condition을 이용한 동기화
- 동기화할 수 있는 방법은 synchronized 블럭 외에도
'java.util.concurrent.locks' 패키지가 제공하는 lock 클래스들을 이용하는 방법이 있다.
이 패키지는 JDK 1.5에 와서야 추가된 것으로 그전에는 synchronized 블럭뿐이었다.
- synchronized 블럭으로 동기화를 하면 자동적으로 lock이 잠기고 풀리기 때문에 편리하다.
심지어 synchronized 블럭 내에서 예외가 발생해도 lock이 자동적으로 풀린다.
그러나 때로는 같은 메서드 내에서만 lock을 걸 수 있다는 제약이 불편하기도 하다.
그럴 때 이 lock 클래스를 사용한다.
lock 클래스의 종류는 다음과 같이 3가지가 있다.
ReentrantLock 재진입이 가능한 lock, 가장 일반적인 배타 lock
ReentrantReadWriteLock 읽기에는 공유적이고, 쓰기에는 배타적인 lock
StampedLock ReentrankReadWriteLock에 낙관적인 lock의 기능을 추가
- ReentrantLock은 가장 일반적인 lock이다.
'Reentrant'라는 단어가 앞에 붙은 이유는, 특정 조건에서 lock을 풀고
나중에 다시 lock을 얻고 임계영역으로 들어와서 이후의 작업을 수행할 수 있기 때문이다.
지금까지 우리가 lock이라고 불러왔던 것과 일치한다.
- ReentrantReadWriteLock은 이름에서 알 수 있듯이,
읽기를 위한 lock과 쓰기를 위한 lock을 제공한다.
ReentrantLock은 배타적인 lock이라서 무조건 lock이 있어야만 임계 영역의 코드를 수행할 수 있지만,
ReentrankReadWriteLock은 읽기 lock이 걸려있으면, 다른 쓰레드가 읽기 lock을 중복해서 걸고 읽기를 수행할 수 있다.
- 읽기는 내용을 변경하지 않으므로 동시에 여러 쓰레드가 읽어도 문제가 되지 않는다.
그러나 읽기 lock이 걸린 상태에서 쓰기 lock을 거는 것은 허용되지 않는다.
반대의 경우도 마찬가지다.
일기를 할 때는 읽기 lock을 걸고, 쓰기 할 때는 쓰기 lock을 거는 것일 뿐 lock을 거는 방법은 같다.
- StampedLock은 lock을 걸거나 해지할 때, 스탬프'를 사용하며,
읽기와 쓰기를 위한 lock외에 '낙관적 읽기 lock(optimistic reading lock)'이 추가된 것이다.
읽기 lock이 걸려 있으면, 쓰기 lock을 얻기 위해서는 읽기 lock이 풀릴 때까지 기다려야 하는데 비해,
'낙관적 읽기 lock'은 쓰기 lock에 의해 바로 풀린다.
- 그래서 낙관적 읽기에 실패하면, 읽기 lock을 얻어서 다시 읽어 와야 한다.
무조건 읽기 lock을 걸지 않고, 쓰기와 읽기가 충돌할 때만 쓰기가 끝난 후에
읽기 lock을 거는 것이다.
'자바의 정석' 카테고리의 다른 글
[자바의 정석 1권] Object 클래스 (0) | 2025.05.15 |
---|---|
[자바의 정석 2권] wait()와 notify() (0) | 2024.12.30 |
[자바의 정석 2권] volatile (0) | 2024.12.30 |
[자바의 정석 2권] TreeSet (0) | 2024.12.24 |
[자바의 정석 2권] HashSet (0) | 2024.12.24 |