본문 바로가기

Programing/멀티코어,병렬,멀티스레드

CriticalSection에 관해..

출처 http://kuaaan.tistory.com/99

Q1: 동일한 스레드에서 동일한 CriticalSection에 두번 진입하면 Block이 걸릴까?
A1: 아니다. 스레드가 이미 자신이 소유한 CriticalSection을 다시 소유하려고 시도하는 것은 전혀 문제될 것이 없다. CriticalSection 개체는 내부적으로 LockCount와 OwningThread라는 멤버가 있어서 자신이 몇번 Lock이 걸렸는지와 어느 스레드에 소유되었는지를 기억하고 있다. 
다른 스레드가 소유한 CriticalSection 개체에 대해 EnterCriticalSection을 시도하면 당연히 Block되겠지만, CriticalSection을 소유한 스레드가 다시 EnterCriticalSection을 시도하면 즉시 리턴되고, 내부적으로 LockCount가 하나 증가한다. 대신, EnterCriticalSection한 횟수만큼 LeaveCriticalSection을 호출해주어야 CriticalSection 개체가 Signaled 상태로 돌아온다. 두번 EnterCriticalSection한 후 한번만 LeaveCriticalSection하면? 당연히 한번 EnterCriticalSection했을 때의 상태와 동일해진다.

디버거에서 CriticalSection 개체를 들여다 보면 아래와 같은 멤버들로 구성된 것을 알 수 있다. LockCount의 초기값은 -1이고, 한번 소유되면 0으로 증가한다.

※ 참고로... linux의 posix mutex는 lock을 두번 걸 경우 데드락에 걸리는 문제가 있었다.


Q2: A라는 스레드가 소유한 CriticalSection을 B라는 제3의 스레드가 해제할 수 있나?
A2: 그렇다. CriticalSection에 진입할 때는 Thread를 확인하지만 Leave할때는 확인하지 않으며, 임의의 스레드라도 CriticalSection을 해제할 수 있다.

Q3: 어느 Thread에도 소유되지 않은 CriticalSection에 대해 LeaveCriticalSection을 호출하면 어떻게 되나?
A3: 이런 일이 벌어져선 안된다 ㅡ.ㅡ. LeaveCriticalSection을 호출하면 LockCount가 초기값인 -1에서 하나 더 감소하여 -2가 된다. 이 상태에서는 LeaveCriticalSection을 호출했던 스레드를 포함하여 어떠한 스레드도 EnterCriticalSection을 할 수 없게 된다. (시도하면 Block된다.)
이런 경우 CriticalSection을 삭제하고 다시 만드는 방법밖에 없다.

Q4: CriticalSection을 소유한 Thread가 죽어버리면 CriticalSection은 Lock이 풀릴까?
A4: 풀리지 않는다. (반면에 커널객체인 Mutex나 Event 등은 소유한 Process가 죽으면 소멸된다.) 따라서 이런 일이 벌어지면 Application이 Hang 걸려버리는 경우가 생긴다. 단, 위에서 언급한 바와 같이 소유한 Thread가 죽어버린 CriticalSection을 제 3의 Thread가 LeaveCriticalSection 해줄 수는 있다.

※ Mutex의 경우 해당 개체를 소유한 Thread가 죽으면 자동으로 Signaled 상태로 변경된다. 즉, 저절로 Lock이 풀리게 된다. 이때 WaitForSingleObject()로 대기중이던 스레드는 함수 리턴값으로 WAIT_ABANDONDED 을 받게 된다. (CriticalSectioin과 Mutex의 차이)

출처 : http://kuaaan.tistory.com/99