공유자원
각 프로세스, 스레드가 접근할 수 있는 자원 or 변수
경쟁 조건
- 공유 자원을 두 개 이상의 프로세스가 동시에 읽거나 쓰는 상황
- 공유 데이터에 동시 접근하거나, 동시에 업데이트하려는 과정에서
접근 순서에 따라 결과가 달라질 수 있는 현상을 이야기함
임계영역
경쟁 조건이 발생하는 코드 영역
공유 자원을 접근하므로, 동시에 두 스레드가 실행해서는 안되는 코드
원자적으로 수행되면 문제가 생기지 않음
그러나, 쓰기 작업을 할 때 아래와 같이 3단계의 명령어로 구성되어 일관성 문제 발생
상호 배제 (Mutual Exclusion)
반드시 하나의 스레드만 임계영역을 실행하도록 보장하는 기법
임계영역을 해결하기 위한 방법 3가지
뮤텍스 (= 락)
프로세스나 스레드가 공유자원을 Lock()으로 잠금 설정하고 락 소유권을 얻고 임계영역에서 작업을 함
작업 후 Unlock()을 통해 잠금을 해제하여 다른 개체가 접근할 수 있게 함잠금이 설정되는 동안은 다른 프로세스, 스레드가 접근할 수 없음
락을 기다리는 스레드들은 Busy Waiting에 빠지게 되는데,
이 때 Sleep을 하여 대기 큐에 넣고, 사용가능할 때 스레드를 깨운다.Lock 동작 원리 (= 스핀락 & Busy Waiting)
두 스레드 A, B가 공유 자원에 접근할 때, A가 락 소유권자이다.
B가 임계영역에 접근을 위해 Spin Lock을 하게 되는데, 이 때 Busy Waiting을 해결하기 위한 해결책을 설명해달라Busy Waiting
= 바뀌지 않을 값을 기다리면서 CPU를 계속 소모하는 것위 경우 B 스레드가 계속 자신이 접근해도 되는지 검사를 요청할텐데 이게 비용이 많이 발생할 것이다.
해결책과 단점
```
시스템 API
yield() = CPU를 포기하여 프로세스가 실행중 → 레디 상태로 됨
- park() + unpark()
- `park()` : 스스로 대기 상태로 전이
- `unpark()`: threadID로 지정된 스레드를 깨움
```
1. 무조건 양보 방식
CPU 점유권을 포기하고 다른 스레드에게 기회를 줌
B 스레드를 무조건 대기 상태로 보내면,
레디큐에 다른 스레드가 없을 시 **컨텍스트 스위칭 비용이 과도**해질 수 있음
2. 큐 사용: Sleep Lock
B 스레드를 큐에 추가하고 Blocked 상태로 전환
A 스레드가 락을 해제하면 큐에 있는 B 스레드를 깨워 실행시킴
3. 두 단계 락
세마포어
일반화된 뮤텍스로, 간단한 정수 값과 wait, signal로 공유 자원에 대한 접근 처리
프로세스가 공유 자원에 접근하면 세마포어에서 wait(),
해제하면 세마포어에서 Signal()을 수행세마포어에는 조건 변수가 없고, 세마포어 값 수정 시 다른 프로세스는 동시 수정이 불가능하다
식사하는 철학자
철학자들 사이에 포크가 있고, 양쪽 포크를 집어야 식사가 가능하다
그러나 동시에 포크를 집으려하면 영원히 기다리는 교착상태에 빠짐
이를 해결하기 위해 원형큐를 사용.
모든 철학자는 왼쪽 포크부터 잡지만, 마지막 철학자만 오른쪽 포크를 먼저 집게 하면 된다.
교착상태
두 개 이상의 프로세스, 스레드가 서로가 가진 자원을 기다리며 중단된 상태
(= 데드락)
교착상태 원인
아래 4가지를 모두 충족해야 교착 상태가 발생함 !
- 상호배제
- 한 번에 한 쓰레드만 자원을 사용
- 사용중인 자원을 다른 프로세스가 사용하려면 요청한 자원이 해제될 때까지 기다림
- 점유와 대기
- 최소한 하나의 자원을 점유한 스레드가
다른 스레드가 점유한 자원을 추가로 요구하며 대기함
- 최소한 하나의 자원을 점유한 스레드가
- 비선점
- 스레드가 점유한 자원을 강제로 뺏지 못함
- 순환 대기
- 스레드의 자원 점유와 대기가 원형으로 연결됨
교착상태 해결방법
위 4가지 중 하나라도 끊으면 됨
- 예방
- 제일 비용이 많이 듬, 동시성 효과 감소
- 데드락이 아예 안 생기게 함,
동시성이 줄어서 실행시간이 증가하는 단점이 있음
- 회피
- OS 단계에서 스케줄링을 하여 OS 비용이 발생할 수 있음
- 프로세스 당 요청할 자원들의 최대치를 통해 자원할당 가능 여부를 판단하는 *은행원 알고리즘을 사용함
- 총 자원의 양과 현재 할당한 자원의 양을 기준으로 안정, 또는 불안정 상태로 나누고 안정 상태로 가도록 자원을 할당함
- 탐지 및 회복
- 교착 상태를 허용하고 모니터링하면서 해결함
- 크루스칼 알고리즘을 통해
- 무시
iOS에서 데드락 해결 방법
Serial Queue + sync 조합
Concurrent Queue + Dispatch Barrier
DispatchQueue의 flags를 설정해주면 됨
'📱 iOS > Swift Concurrency' 카테고리의 다른 글
[Swift Concurrency 6편] Swift Concurrency 등장 배경 (1) | 2025.02.26 |
---|---|
[Swift Concurrency 5편] 동시성 프로그래밍 with GCD (0) | 2025.02.25 |
[Swift Concurrency 4편] 직렬-동시, 동기-비동기 (0) | 2025.02.24 |
[Swift Concurrency 2편] Process & Thread (0) | 2025.02.22 |
[Swift Concurrency 1편] OT (0) | 2025.02.21 |