경쟁 상태(Race Condition)
둘 이상의 프로세스가 읽거나 쓸 때 타이밍이나 순서에 따라 결과 값이 달라질 수 있는 상태
임계 구역(Critical Section)
여러 프로세스가 공유하는 자원에 대해 한번에 둘 이상의 프로세스가 접근해서는 안되는 영역. 한번에 여러 스레드가 접근하여 값을 변경하면 데이터의 일관성이 깨지는 race condition이 발생할 수 있다.
- 상호 배제(mutual exclusion): 특정 프로세스가 크리티컬 섹션에서 실행되면 다른 프로세스는 크리티컬 섹션에서 실행 불가
- 진행(progress): 자기 크리티컬 섹션에서 실행되는 프로세스 없고 해당 크리티컬 섹션에 진입하려고 하는 다른 프로세스들 있으면 나머지 구역에서 실행중이지 않은 프로세스들만 다음 누가 그 임계구역에 진입할 수 있는지 결정하는데 참여할 수 있으며, 이 선택은 한정된 시간 내에 수행된다. -> 임계구역 비어 있으면 적절하게 순서 선택해서 진입.
- 한정된 대기(bounded waiting): 프로세스가 자기의 크리티컬 섹션에 진입하려는 요쳥 후 다른 프로세스들이 그들 자신의 임계구역에 진입하도록 허용되는 횟수에 한계가 있다.
뮤텍스(Mutex, Mutual Exclusion)
- 두 처리 단위가 동시에 임계구역에 진입하지 못하게 하는 방법
- 좁은 의미로는, 임계구역 제어를 위해 사용하는 lock 객체. 한번에 하나의 스레드만 진입할 수 있도록 함
Acquire: 락 획득
Release: 락 제거
Acquire( ) {
While (!available) busy wait; // 대기
available = false;
}
Release( ) {
Available = true;
}
int getchar()
{
int pos;
char ret;
lock(keymutex); /* entry section */
/* critical section begin */
pos = head;
ret = queue[pos];
pos = (pos + 1) % 32;
head = pos;
/* critical section end */
unlock(keymutex); /* exit section */
return ret; /* remainder section */
}
세마포어(semaphore)
- 공유 자원이 여러개인 경우 공유 자원에 대한 접근을 제한하는 방법
- 두개의 원자적 함수로 조작되는 정수 변수
- S: 세마포어 정수 값
- P: 임계구역 진입에 사용하는 원자적 함수
- V: 임계구역 탈줄에 사용하는 원자적 함수
P(S) {
S--;
if S < 0
// 이 프로세스를 재움 큐에 추가 (잠 듦)
}
V(S) {
S++;
if S <= 0
// 재움 큐로부터 프로세스를 제거 (깨어남)
}
튜링 동치
컴퓨터 P와 Q가 있을 때, P가 할 수 있는 일을 Q로 표현 가능(simulate)하고, Q가 할 수 있는 일을 P로 표현 가능하다면 P와 Q는 튜링 동치다.
뮤텍스, 세마포어와 튜링 동치
뮤텍스 - 세마포어는 튜링 동치다.
- 세마포어 => 뮤텍스 구현: 세마포어의 count 값을 1로 두면 mutex의 동작을 표현할 수 있다.
- 뮤텍스 => 세마포어 구현: wait / signal의 원자성을 구현할 때 mutex를 이용
class Semaphore {
private:
int count; // 세마포어 카운터
std::mutex mtx; // 뮤텍스
std::condition_variable cv; // 조건 변수
public:
Semaphore(int initial_count) : count(initial_count) {}
// 획득 (P 연산)
void wait() {
std::unique_lock<std::mutex> lock(mtx);
while (count == 0) {
cv.wait(lock); // 카운터가 0일 때 대기
}
count--; // 카운터 감소
}
// 해제 (V 연산)
void signal() {
std::unique_lock<std::mutex> lock(mtx);
count++; // 카운터 증가
cv.notify_one(); // 대기 중인 스레드 중 하나를 깨웁니다.
}
};
획득 / 해제 연산에 진입할 때 mutex lock을 걸면 스레드의 수가 많더라도 원자적으로 처리할 수 있다. 따라서 mutex를 통해 Semaphore의 동작을 표현할 수 있다.
mutex를 semaphore로 구현할 수 있다는 것은 생각했지만, semaphore을 mutex로 구현 가능한지는 고민해본 적이 없던 것 같다. 연산에 mutex 락을 거는 등의 방식을 통해 semaphore을 묘사할 수 있다는 것을 잘 기억해둬야 겠다.
'CS > 운영체제' 카테고리의 다른 글
[운영체제] 파일시스템 (0) | 2022.05.31 |
---|---|
[운영체제] 가상 메모리 ( Virtual Memory ) (0) | 2022.05.19 |
[운영체제] 페이징 기법 (0) | 2022.05.16 |
[운영체제] 메모리 (0) | 2022.05.09 |
[운영체제] 데드락 (0) | 2022.04.30 |