1) Java 모니터
- java 초창기 부터 제공된 기능
- 병생성을 위한 BoundedBuffer 클래스를 제공한다. → 여기에 생성된 자원을 넣고 빼고 함
- 관련 메서드
- insert() : 생산자가 만든 자원을 BoundedBuffer에 넣는 메서드, 만약 버퍼가 꽉찼다면 대기 집합으로!
- remove(): 소비자가 BoundedBuffer에서 자원을 꺼내는 메서드, 버퍼에 자원이 없다면 대기 집합으로!
- wait() : 스레드의 락을 해제하고, 버퍼에 넣거나 빼질 못할 경우 봉쇄상태로 변경후, 대기큐로 이동
- notify() : 대기 집합의 임의의 스레드 선택후, 진입 집합으로 이동, 봉쇄 상태 해제
- 진입 집합 : 락을 획득하기 위한 집합
- 대기 집합 : insert(),remove() 메서드를 완전히 수행하지 못할 경우 대기하는 곳
public synchronized void insert(E item){
while(count == BUFFER.SIZE){
try{
wait();
}
catch (InterruptedException ie){}
}
buffer[in] = item;
in = (in +1) % BUFFER.SIZE;
count++;
notify();
}
public synchronized void remove(E item){
while(count == 0){
try{
wait();
}
catch (InterruptedException ie){}
}
item = buffer[out]
out = (out + 1) % BUFFER.SIZE;
count--;
notify();
}
- 진행 ( 가정 : 버퍼가 가득 찬 경우 )
- insert() 메서드를 실행하였으나 wait() 에 의해 락을 반납하고 대기 집합으로 이동
- 소비자는 락이 생겨 remove()로 접근이 가능해져 실행 한 후 notify() 실행, 소비자가 아직 락 소유
- notify() 호출은 대기 집합의 소비자를 제거하고 진입 집합에 넣는다.
- remove() 메서드 종료 및 락 해제
- 진입 가능한 생산자가 다시 insert() 실행 후 wait()를 실행해 삽입이 가능한지 확인 후 삽입, 대기 집합에 스레드가 없으면 notify() 호출은 무시, 메서드 종료시 락 또한 해제
2) 재진입 락 (Reentrant Locks)
- sychronized 와 동일한 명령문처럼 작동 (공정성 매개변수가 따로 있는게 차이점 - 무한대기방지를 위해)
- ReentrantLock은 단일 스레드가 소유하며 공유 자원에 대한 상호 배타적 액세스를 제공하는 데 사용
- 관련 메서드
- lock() : 락을 사용할 수 있거나, 이미 락을 소유한 스레드(재진입 락이라 불리는 이유)가 이 메서드를 호출한 경우 lock()는 호출 스레드에게 락 소우권을 주고 제어를
return
한다.
- unlock(): 락을 해제할 때 사용함, 반드시 finally를 통해 항상 마지막에 락을 해제하도록 한다.
- Reader가 많은경우 매우 보수적일 수 있다. 하지만 ReentrantReadWriterLock을 사용해 이러한 단점을 보완할 수 있다 → Reader - Writer 방식처럼 하나의 Writer 에 여러 Reader가 존재할 수 있다.
Lock key = new ReentrantLock();
key.lock();
try{
/* 제어를 얻어 임계구역에 진입 */
}
finally{
key.unlock();
}
------------------------------------------------------------------
// 아래처럼 두 번의 락을 획득하는 것의 불필요한 경쟁을 피하기 위한 재진입 락
public void function(){
lock()
funciontB();
unlock();
}
public void functionB(){
lock();
~~~
unlock();
}
3) 세마포
Semaphore(int value); // value는 초기값을 지정
/*예시*/
Semaphore sem = new Semaphore(1);
try{
sem.acquire(); //카운팅으로 임계구역 진입 등등
/* critical section */
}
catch (InterruptedException ie) {}
finally {
sem.release(); // 세마포 해제
}
4) 조건 변수
- 처음에 설명한 모니터 방식에 재진입 락 방식과 조건 변수를 섞은 버전이다.