작성
·
213
0
while(true)
{
int expected = 0;
int desired = 1;
if (Interlocked.CompareExchange(ref _locked, desired, expected) == expected)
break;
Thread.Yield();
}
이 코드를 정리를 해보면
만약에 A 쓰레드가 있고, B쓰레드가 있다
A쓰레드가 공유 자원을 점유하고 있으면
lock이 0에서 1로 바뀌고
B 쓰레드는 접근 하려니까 lock이 1이니까 계속 무한 루프를
돈다. 이것은 성능상의 저하를 불러 일으킨다.
왜? 쓸데없는 행동이기 때문에 따라서
A쓰레드가 공유자원을 사용을 끝날 때 까지
B쓰레드를 무한루프를 돌게 하지말고 재우는데
Thread.sleep, yeild.. 뭐 이런 함수를 이용해서
재우는데
그럼 무한 루프가 잠시 멈추는 상황이잖아요?
그럼 a쓰레드가 공유자원을 쓰고 나왔다는 것을
어떻게 알 수 있나요? 검색 해보니까 sleep을 os가 깨운다는데
그럼 정리를 해보면 면접관님 께서 만약 이런 질문을 하시면
일단 OS가 A 쓰레드가 할일을 끝냈으니, 잠자고 있던
B쓰레드를 깨워서 그때부터 반복을 해서 다시 LOCK 검사를
진행합니다.
LOCK 변수 값이 0이라면 컨텍스트 스위칭이 일어나는데
A 쓰레드의 정보가 레지스터에서 지워지고 B 쓰레드 정보가
채워짐으로써 B 쓰레드가 CPU를 점유하고 이제 B쓰레드가
공유자원 _num변수를 사용해서 _num++연산이 진행이
됩니다. 이렇게 저는 해당 챕터 강의를 이해 하고 정리를 했거
든요 혹시 틀린 점이 있다면 알려주심 감사하겠습니다.
아 그 sleep 걸어놓고 os가 깨우는 거 맞는지도 알려주시면
감사하겠습니다. ^^
답변 1
0
그럼 a쓰레드가 공유자원을 쓰고 나왔다는 것을
어떻게 알 수 있나요? 검색 해보니까 sleep을 os가 깨운다는데
-> 물론 알 수 없습니다.
비행기 화장실에서 누가 있으면 그냥 자리에 앉았다가
대충 5분 후 다시 오는 느낌으로,
잠시 한숨 자고 (Sleep) 오는 것이죠. (강의에서 '랜덤 메타'라 표현한 것)
정말 알고 싶으면 Event를 이용해서 A->B 통보하는 방식이 있지만
이는 커널 자원을 추가로 사용하는 것입니다. (강의에서 '갑질 메타'라 표현한 것)
일단 OS가 A 쓰레드가 할일을 끝냈으니, 잠자고 있던
B쓰레드를 깨워서 그때부터 반복을 해서 다시 LOCK 검사를 진행합니다.
-> 말씀하신건 Event 방식의 동기화입니다.
현재는 그냥 OS가 일정 시간이 지나면 깨우고,
그 때 다시 한 번 Lock 검사를 시도하는 것이죠.
아 그 sleep 걸어놓고 os가 깨우는 거 맞는지도 알려주시면 감사하겠습니다. ^^
-> Sleep 한다고 영구적으로 잠자는 것은 아닐테고,
당연히 누군가는 깨워줄텐데 그것은 OS의 역할이 맞습니다.
원래 OS가 프로세스마다 실행할 시간 (timeslice)를 할당해주는데,
경우에 따라 프로세스가 sleep yield 등을 통해
그 정당한 권리를 한 턴 포기한다고 보시면 됩니다.
그러면 다음 턴에서 OS가 깨워서 또 실행을 해주겠죠.