32장: Common Concurrency Problems
병행성 특징
장점
- 처리율 향상
- 멀티 스레드의 장점
단점
- 오류 발생 가능성이 높음
- 교착 상태 오류
- 비 교착 상태 오류
비교착 상태 오류
원자성 위반
작업을 원큐에 못 끝내는 경우들
ex) 인터럽트 당하면 안되는 것들
- 직렬성 보장 필요
- 공유변수에 락 사용
순서위반
A 작업을 해야 B 작업을 할 수 있는 스레드 작업
- 공유 변수 접근 순서 역전을 막기 위해
- 조건 변수로 초기화
교착 상태
데드락이 발생하는 코드
데드락은 왜 발생하는가 ?
- 복잡한 의존성
- 캡슐화의 특성
교착상태 발생조건 4가지
아래 중 단 하나라도 만족하지 않으면,
교착 상태는 일어나지 않음
즉, 하나라도 안 일어나게 해야 함
- 상호 배제
한 번에 한 스레드만 자원을 사용 - 점유와 대기
최소한 하나의 자원을 점유한 스레드가
다른 스레드 작업을 요구하며 대기 - 비선점
스레드가 점유한 자원을 강제로 뺏지 못함 - 순환 대기
스레드의 자원 점유와 대기가 원형으로 연결
교착 상태 처리
- 교착상태 예방
비용 증가, 동시성 줄어듬, 데드락 피해가 큼 - 교착상태 회피
- 교착상태 탐지 및 회복
- 교착상태 무시
비용 적음, 동시성 증가, 데드락 피해가 적음
교착상태 예방
1. 순환 대기 예방하기
절대 순환이 생기지 않게 하면 됨
획득하는 전체 순서를 정해두면 됨
L1, L2 락이 있다면 무조건 L1부터 집어야 L2 되게끔
2. 점유와 대기
모든 자원을 동시에 획득하고,
동시에 해제하도록 강제
- 병행성/효율성 감소
- 캡슐화와 맞지 않음
3. 비선점
요청하는 자원을 대기중인 스레드가 점유중이면,
강제 선점함
- trylock() 활용하기
만약, 다른 스레드가 lock(L2), tryLock(L1)의 순서로 같은 시도를 한다면 ?
Livelock의 문제
각 스레드가 반복적으로 실행하지만,
아무도 못 얻고 무한반복
→ 두 개의 스레드가 거울처럼 동작하면, 대칭성을 끊어주면 됨
두 번째 Lock을 얻기 전에 Sleep을 하게 하면 됨
4. 상호배제
반드시 상호배제가 보장되어야 할 때가 있음
그래서 Lock-free 방식 or Wait-free 방식 사용
void AtomicIncrement(int* value, int amount) {
do {
int old = *value;
}while(CompareAndSwap(value, old, old+amount) == 0);
}
- 락을 획득해서 값 갱신 후 해제하는 대신에
CompareAndSwap을 통해 값에 새 값을 갱신하도록 반복적으로 시도함 - 락을 획득할 필요가 없음 = 교착 상태 X
Lock 없이 상호배제 영역을 줄여서 데드락을 줄임
스케줄링: 교착상태 회피
교착 상태가 일어나지 않도록 스케줄링
각각의 락을 누가 사용/요청하는지 알아야 함
Q. 2개의 CPU에서 4개의 스레드 실행하는 경우
- T1이 L1, L2 필요
- T2도 L1, L2 필요
- T3는 L2 필요
- T4는 필요 X
T1, T2만 서로 동시에 실행 안 하면 상관없음
만약 더 복잡해진다면 ?
데드락은 발생하지 않으나,
반환 시간이 길어지게 됨
교착상태 탐지 및 회복
교착상태 발생 허용 → 사후 감지 및 회복
감지
- 주기적인 시스템 감지
- 자원할당 그래프를 구축하여 사이클 점검
회복
- 운영자가 수작업 처리
- 자동 - 사이클 제거될 때까지 희생자 선택해서 자원 회수
'🖥️ Computer Science > Operating System' 카테고리의 다른 글
[OS] 31장: Semaphore (0) | 2024.07.04 |
---|---|
[OS] 30장: Condition Variables (0) | 2024.07.03 |
[OS] 28장: Locks (0) | 2024.07.02 |
[OS] 19장: TLB (Translation Lookaside Buffers) (1) | 2024.07.01 |
[OS] 18장: 메모리 가상화의 Paging (0) | 2024.06.30 |