Creative Commons License

Microsoft .NET

닷넷!시작하기
닷넷! Ver 2.0~
닷넷!스킬업
웹개발
윈폼개발
실용모듈개발
Tip & Tech
하루 한 문법

Microsoft .NET 개발자들을 위한 공간입니다. 기초강의에서 부터 고급 기술 정보 및 팁등을 다루도록 하겠습니다.

.

닷넷!스킬업

닷넷 기술을 조금 더 깊이 다루고자 합니다. 특정 주제를 정하지 않고 이슈 발생 시 마다 체계적으로 정리하여 공유하겠습니다. 이전 자료를 옮겨온 곳이기도 합니다.

[Thread] [동기화] Monitor 클래스

작성자 : 박종명
최초 작성일 : 2008-06-16 (월요일)
최종 수정일 : 2008-06-16 (월요일)
조회 수 : 2668

앞서 공급자/소비자 문제에서 공유 자원에 대한 접근제어(동기화) 방법으로 닷넷에서 제공하는 Monitor 클래스를 사용하였다.

 

이번 글에서는 Monitor 클래스에 대해 자세히 알아보자.

 

 

* Monitor 클래스

System.Threading 네임스페이스에 있는 Monitor 클래스는 멀티 Threading 환경에서 Thread 간에Lock,
wait/signals
이용하여 개체(객체) 접근에 대한 동기화를 제공하는 클래스이다.

 

멀티 Thread 환경에서 여러 Thread 가 공유하는 리소스가 있다면 이 리소스에 대한 접근은 다음과 같은
보장(동기화)이 이루어 져야 한다.

-         하나의 Thread 가 공유리소스에 접근하면 다른 Thread 는 그 리소스에 대한 접근이 통제되어야 한다

-         같은 의미로 한번에 하나의 Thread 만이 공유 리소스에 접근할 수 있어야 한다

 

 

1.1  Monitor 클래스 특징

a.       객체 단위의 동기화를 지원한다. 즉 동기화를 위해 클래스의 인스턴스(참조타입)를 필요로 한다.
값 형식에 대해 잠금을 시도 하면 Object 타입으로 Boxing 이 일어난다.

b.       하나의 Thread 가 객체에 대한 lock을 걸면 다른 Thread 에 의해 또다시 lock 될 수 없다.
, 객체에 대한 잠금은 하나의 Thread 에서만 걸 수 있다. 이 잠금이 풀려야 다른 Thread에서 또 잠금을 걸 수 있다.

c.       Monitor 클래스의 인스턴스를 생성하지 못한다.

d.       Monitor 클래스의 멤버는 모두 static 이다.즉 클래스의 이름으로 접근해야 한다.

 

 

 

1.2  Monitor 멤버

 

a.       Enter(object obj)
obj
에 대한 (단독) 잠금을 가진다. , 해당하는 객체에 대해서 Monitor lock 을 얻는 메서드 이다.

      이미 한 Thread1 에서 Enter 을 실행하여 객체(obj)에 대한 잠금을 가진 상태에서 다른 Thread2 가 이 객체(obj)에 대한 Enter 을 호출하면       Thread1 가 객체(obj)에 대한 잠금을 해제 할 때 까지 Thread2는 차단(blocking) 된다.
 

b.       Exit(object obj)
obj
에 대한 (단독) 잠금을 해제 한다. Enter 를 통해 얻은 Monitor lock 를 반환한다.
Exit
메서드는 Enter 메서드 호출과 반드시 같은 수 사용되어야 한다. Enter 과 같은 수 만큼 호출하지 않으면 개체의 잠금이 해제되지 않는다.

 

c.       Wait(object obj)
obj
에 대한 잠금을 해제하고 대기열로 들어간 다음 잠금을 가질 때 까지 현재 Thread 를 차단한다.
Enter
메서드와 Exit 메서드 내부에서 사용하며
다른 Thread로부터 신호를 기다리게 된다.
, Thread1 Enter 을 통해 객체의 잠금을 획득하고 난 후 Wait 를 호출하면 이 객체에 대한 잠금을 해제하게 되며 다른 Thread2 가 이 객체에 대한 
잠금을 획득할 수 있도록 한다.다른 Thread2 가 잠금을 해제 할 때 까지 Thread1 은 차단된다.그리고 잠금을 가진 Thread2 Pulse 또는 PulseAll 을 호출하면 Thread1에 신호가 가고 Thread1은 객체에 대한 잠금을 다시 가질 수 있게 된다
만일 Wait 로 대기중인 Thread 가 있는 상태에서 다른 Thread 들에서 Pulse/PulseAll이 호출되지 않으면 Thread1는 무한 대기 상태로 빠지게 됨을 주의해야 한다.

 

d.       Pulse(object obj) / Pulse All(object obj)
객체(obj)의 잠금 획득을 위해 (Wait 호출 이후) 기다리고 있는 Thread ()에게 객체의 상태 변경을 알린다. 잠금을 획득한 소유자 만이 Pulse 를 호출 할 수 있다.
Pulse
는 대기열에 대기중인 Thread 들 중 맨 앞의 Thread 에게만 신호를 보내는 반면,PulseAll 은 대기열에 대기중인 모든 Thread 에게 객체(obj) 의 상태변경 신호를 보낸다.

 

 

1.3   공급자/소비자 문제로 본 Monitor 흐름

앞서 공급자/소비자 환경에서의 Thread 간 공유 리소스 접근 동기화를 위해 Monitor 클래스를 사용하였다.

공급자/소비자 문제로 객체에 대한 잠금,대기,해제 등의 흐름을 살펴 보자.
(소스 코드는 앞의 글을 참고 하기 바란다)

 

Flow 에서는 엄마 Thread와 아이 Thread 가 동시에 밥상객체에 접근하려고 하며 아이 Thread 가 먼저 리소스에 접근 하였다고 가정한다.



Child Enter :  아이(Child) 밥상(Table)에 대한 접근을 위해 단독 잠금을 요청한다.

Mother Enter : 엄마(Mother)는 밥상(Table)에 대한 잠금을 요청하지만 Child 가 이미

                     Table에 대한 잠금을 가졌기 때문에 Blocking 된다.

Wait : 밥상(Table) 이 준비가 되지 않았기 때문에 Wait 를 호출하여 자신이 가지고 있던 잠금을
        
해제하고 대기열로 들어간다.

④ 밥 차림 & Pulse : 아이(Child)의 밥상(Table)에 대한 잠금이 해제 되었기 때문에 엄마(Mother)

밥상(Table)의 잠금을 획득하게 되고 밥을 차린 후 Wait 되어 있던

아이(Child) 를 깨운다(신호를 보낸다)

⑤ 잠금 획득준비 : 엄마(Mother)로부터 밥상(Table) 에 대한 접근이 가능하다는 신호를 받아서

밥상(Table)에 대한 잠금을 획득하려 준비한다

Exit : 엄마(Mother)은 밥상(Table)에 대한 잠금을 완전히 해제한다.

⑦ 잠금 획득 & 밥 먹기 : 아이(Child)는 밥상(Table)에 대한 잠금을 획득하고 밥을 먹는다.

 

이하 계속 (생략

위의 그림에서 대기열은 Wait 를 호출한 Thread가 객체 잠금을 해제한 후 다음 잠금획득을 위해 객체의 대기중인 대기열로 들어가는 현상을 나타낸 것이다.

 

이하 계속 과정은 아이가 밥을 다 먹고 난 후 엄마가 또 밥을 차리는 과정부터가 생략되었다.

엄마는 총 3번의 밥상을 차리고 아이는 총 3번의 밥을 먹는다(아침/점심/저녁). 이 과정은 위의 과정과 완전 동일하게 동작할 것이다. 결국 엄마가 밥을 다 차리기 전에는 아이가 밥상에 접근하지 못하며 아이가 밥을 다 먹기 전에는 엄마는 밥상에 접근하지 못하게 되는 것이다.

 

 

1.4  Monitor 이용 시 주의 사항

앞의 글의 전개에서 Monitor을 사용함에 있어 주의해야 할 사항들은 빨간색 표시를 해 두었다. 그리고 마지막으로 한가지가 더 있다. 다음코드를 살펴 보자

 

Monitor.Enter(object obj)
 
ß 개체 잠금 후 실행하는 부분

Monitor.Exit(object obj)

 

만일 위의 코드에서 <- 표시된 영역에서 Exception 이 발생한다면 모든 대기중인 Thread 무한 대기 상태로 빠져 버릴 수 있다. 따라서 개체 잠금을 해제하는 부분은 Exception 의 발생 유/무와 관계없이 반드시 호출되게 한다.

try{

     Monitor.Enter(object obj)

    

}

finally{

        Monitor.Exit(object obj)

}

 

이름
비밀번호
홈페이지
SP <- 왼쪽의 문자를 오른쪽 박스에 똑같이 입력해 주세요