2020. 6. 4. 14:37ㆍ언어/C#. JAVA
C# lock 키워드를 검색하던 중 설명이 재밌어서 퍼온 글
관련된 이론 분야 : 운영체제론
크리티컬 섹션(임계구역) / 뮤텍스(상호배제) / 세마포어
이것들은 한양대 컴공과 3학년 1학기 과정에 있었던 운영체제론의 핵심적인 내용이었습니다.
허신 교수님의 운영체제론 수업을 들었었는데 이론의 맥을 잘 짚어주셨던 기억이 나네요.
열심히(?) 공부해서 시험도 보고 성적도 좋았지만
막상 그 개념들을 실제로 적용해볼 기회가 없으니 개념이 좀 두리뭉실해서 한 번 정리해 보았습니다.
제가 이해한 내용을 복습하기 위해 정리한 것이라서
틀릴 수도 있으니 많은 성원 바랍니다 (뭔 소리야 ㅋㅋ)
모두 동기화 오브젝트에 관련된 이론인데...
이 이야기를 할 때면 어김없이 나오는게 호프집 화장실에서 똥싸는 이야기더군요 - _ -;;
오늘의 수업은 이름하여...
미쉘린의 호프집 화장실 이론
1. 크리티컬 섹션 (임계구역), Critical Section
호프집에 화장실이 있습니다.
이 화장실에는 변기가 하나밖에 없습니다.
그래서 한 번에 한 사람씩 들어가야 되지욤...
(화장실 안에 서서 기다리면서 누가 똥싸고 오줌싸는걸 지켜볼 수는 없는 노릇)
이 변기가 크리티컬 섹션입니다.
프로그래밍할 때에는 주로 CS (Critical Section)라고 언급됩니다.
MFC 에는 크리티컬 섹션에 대한 클래스가 정의되어 있어서 다음과 같이 사용할 수 있습니다.
CCriticalSection RestRoom;
RestRoom.Lock();
용변보기
RestRoom.Unlock();
Lock() 과 Unlock() 사이의 구간이 크리티컬 섹션입니다.
스레드에서 이렇게 정의한 부분은
한 번에 하나의 스레드만 접근할 수 있습니다.
(스레드에 대한 이야기는 제 지난 컴퓨터 이론 포스트를 참고하시기를...)
호프집에 동수, 일구, 빠박이가 있습니다.
셋이서 신나게 술을 마십니다.
어느순간 세사람 모두 오줌이 마렵습니다.
동수일행 프로세스
CCriticalSection RestRoom; // 전역변수
동수 스레드
{
일구, 빠박이랑 술마시기
if ( 오줌마렵다 )
{
RestRoom.Lock();
용변보기
RestRoom.Unlock();
}
}
일구 스레드
{
동수, 빠박이랑 술마시기
if ( 오줌마렵다 )
{
RestRoom.Lock();
용변보기
RestRoom.Unlock();
}
}
빠박이 스레드
{
동수, 일구랑 술마시기
if ( 오줌마렵다 )
RestRoom.Lock();
용변보기
RestRoom.Unlock();
}
}
지난 포스트에
하나의 주 프로세스가 여러 개의 스레드를 생성하여
CPU 상에서 여러 개의 스레드가 돌아간다는 이야기를 했습니다.
동수, 일구, 빠박이는 모두 각각의 독립적인 스레드입니다.
프로그램이 종료할 때까지 (호프집에서 나갈 때까지)
항상 CPU 상에서 돌아가고 있지요.
술마시다가 어느순간 세 사람 모두 오줌이 마렵습니다.
동수가 먼저 화장실로 냅다 달립니다.
동수 : 일구야 ~ 형 먼저 갈께 ㅜ0ㅜ
일구 : 아 ㅅㅂ~~~
빠박이 : 가지마 ~~~~~
동수가 먼저 가서 용변을 봅니다.
화장실은 한 사람 밖에 들어갈 수 없기 때문에
동수가 화장실에 들어가는 순간 RestRoom.Lock() 이 됩니다.
RestRoom.Lock() 걸리면 다른 스레드는
RestRoom.Lock() 구간에 서서 Unlock() 이 될 때까지 무작정 기다립니다.
...
일구랑 빠박이는 화장실 문앞에 서서 기다립니다.
동수가 용변보고 나오면 RestRoom.Unlock() 이 됩니다.
그럼 이제 일구랑 빠박이중 누군가 먼저 들어간 사람이
RestRoom.Lock() 을 다시 호출하겠지요.
요 화장실 RestRoom Lock() ~ Unlock() 구간이 바로 CS ..... 크리티컬 섹션 입니다.
2. 뮤텍스, Mutex
뮤텍스의 용도는 기본적으로 CS 와 같습니다.
간단하게... 어렵지 않게... 헷갈리지 않게...
차이점만 짚어봅시다.
CS 는 단일 프로세스의 스레드에 대해서만 동작합니다.
반면에, 뮤텍스는 여러 프로세스의 스레드에 대해서도 동작합니다.
동수 일행이 호프집에 들어오는 순간 3 개의 스레드가 생성됩니다.
(동수 / 일구 / 빠박이 스레드)
엇 ??
근데 또 다른 일행이 호프집에 들어왔습니다.
봉팔 일행입니다. (봉팔 / 상팔 / 영팔 ) - 이름만 다를 뿐 동수 일행과 똑같은 프로세스 입니다.
(메모리상에 똑같은 프로그램의 프로세스 2 개가 올라왔다고 생각하면 됩니다. 두 번 실행됐다는 말)
얘들이 들어오면서 또 3 개의 스레드가 생성됩니다.
메모리상에는 6 개의 스레드가 돌아가고 있습니다.
이제...
( 동수 / 일구 / 빠박이 ) // ( 봉팔 / 상팔 / 영팔 )
각각의 스레드가 동시에 화장실에 가지 못하도록 해야 합니다.
이 때, 뮤텍스를 사용합니다.
CS 를 사용하게 되면 중복된 리소스 점유가 발생할 수 있기 때문입니다.
위 코드를 보면
RestRoom 은 동수 일행 프로세스의 전역 변수로 선언되어 있습니다.
그래서 동수 일행끼리는
"동수가 화장실에 갔으니까 일구랑 빠박이는 화장실에 갈 수 없다"
는 사실을 전역변수 CCriticalSection RestRoom 을 통해 명시적으로 알 수 있습니다.
하지만 봉팔 일행은 동수 일행의 RestRoom 과는 또다른
그들만의 RestRoom 을 가지고 있으므로
동수 일행중 누군가가 화장실에 있는지 여부는 판단할 수 없습니다.
그래서...
"지금 화장실에 아무도 없으니까 누구든지 가도 된다" 는 결정을 내립니다.
봉팔이가 화장실로 달려가는 순간
화장실 문이 열리고
동수가 용변보는 모습을 발견합니다 !!
봉팔 : (엇.......!! 아무도 없는줄 알았는데 누가 있잖아 !!)
결국 봉팔이는 용변을 못 보고 예기치못한 사태에 멈춰 서 있게 됩니다.
(실제로 이런식으로 프로그래밍을 하면 런타임 오류가 나지 않을까 생각되네요... 실제로 안해봐서 생각만...;;)
3. 세마포어, Semaphore
복잡하니 쉽게 갑시다...
세마포어는 CS, 뮤텍스가 가지는 특징에 하나를 더 가집니다.
세마포어는 특정 영역의 코드를 실행하는 스레드의 최대 개수를 설정할 수 있습니다.
지금은 1인용 화장실을 언급하였지만...
만약 호프집에서 화장실을 증축하여...
4인용 화장실이 되었다면...
이제 4명까지 화장실에 들어갈 수 있습니다.
이런 카운터를 세마포어로 구현할 수 있고
4인용 화장실
CSemaphore semaphore(0, 4);
첫번째 매개변수 : 리소스 카운터의 초기값
두번째 매개변수 : 리소스 카운터의 최대값
다시 돌아가서...
1인용 화징실에 열쇠라는 개념을 도입하여...
1인용 화장실
CSemaphore key(0, 1);
이런식으로도 활용이 가능합니다.
음...
여기에 또 문제가 생기는데
만약 누군가 1인용 화장실의 열쇠(세마포어)를 가지고 도망가버리면
아무도 화장실에 들어갈 수 없는 문제가 생깁니다.
이건 데드락이라고 하는건데...
오늘은 여기까지 !
다음 기회에 ~~~~~~~~~
p.s : 제 생각을 정리한 내용이니 틀린 내용이 있을 수 있습니다 ;;;;;;
[출처] 크리티컬 섹션, 뮤텍스, 세마포어|작성자 씨피유
https://blog.naver.com/thx4alice/110022369987
'언어 > C#. JAVA' 카테고리의 다른 글
[.NET] IExtenderProvider Interface (feat.ToolTip) (0) | 2021.04.05 |
---|---|
[JAVA] StringTokenizer 사용법 (0) | 2021.01.05 |
[C# 스터디 - Day1] DBHelper 작성하기 (0) | 2020.12.24 |
[C#] txt 파일에 로그 기록하기 (StreamWriter 메서드) (0) | 2020.12.18 |
[C#] WinAPI(Kernel32 dll) 사용하기 (0) | 2019.08.12 |