참고 : youtube - 쉬운코드 를 참고하여 정리한 것임
동기화 매커니즘 세 가지
- 스핀락 Spinlock
- 뮤텍스 Mutex
- 세마포 Semaphore
race condition 경쟁 조건
: 여러 프로세스/스레드가 동시에 같은 데이터를 조작할 때, 타이밍이나 접근 순서에 따라 결과가 달라질 수 있는 상황
synchronization 동기화
: 여러 프로세스/스레드를 동시에 실행해도 공유 데이터의 일관성을 유지하는 것
critical section 임계 영역
: 공유 데이터의 일관성을 보장하기 위해 하나의 프로세스/스레드만 진입해서 실행(mutual exclusion) 가능한 영역
Spinlock
mutual exclusion 을 위해 lock 을 가질 수 있을 때까지 반복해서 시도하는 방법
lock 을 계속 확인하면서 기다리는 동안 CPU를 낭비한다는 단점..
// 예시)
volatile int lock = 0; // global
void critical() {
while (test_and_set(&lock) == 1);
... critical section
lock = 0;
}
int TestAndSet(int* lockPtr) {
int oldLock = *lockPtr;
*lockPtr = 1;
return oldLock;
}
위의 예시는 lock 선언 후 while loop 내에서 lock을 획득한 스레드(T1)가 critical section에 들어와 실행 후 최종적으로 lock을 반환하는 형태로 동작. 다음 스레드(T2)는 이전 스레드(T1)가 끝날 때까지 while loop 내에서 계속 돌게됨 (while 1 == 1 무한루프). T1에서 lock을 다시 초기화해주면 T2도 while문을 탈출해 critical section 에서 작업 완료 후 lock을 반환하고 함수를 종료
TestAndSet은 CPU atomic 명령어로 다음과 같은 특징을 가진다.
- 실행 중간에 간섭받거나 중단되지 않는다
- 같은 메모리 영역에 대해 동시에 실행되지 않는다.
=> atomic하기 때문에 CPU 레벨에서 알아서 동기화 시켜줘서, test_and_set에서 context switching이 일어나 다른 스레드가 실행될 일은 없음.
Mutex
여러 스레드를 실행하는 환경에서 자원에 대한 접근에 제한을 강제하기 위한 동기화 매커니즘 (Mutual Exclusion 상호 배제)
- lock 이 준비될 때까지 스레드를 blocking 하고 대기큐에 넣어 sleep 시키는 방법
CPU 낭비를 최소화 하기 위해 lock() 으로 스레드를 큐에 넣고, unlock() 을 통해 큐에 대기중인 스레드가 있으면 깨우는 방식
- Spinlock과 마찬가지로 atomic한 명령어 사용
value 값을 통해 critical section 영역에 안전하게 들어갈 수 있도록 guard 값도 필요.
Spinlock vs. Mutex
싱글 코어 환경에서는 스핀락의 이점 거의 없음.
멀티 코어 환경일 때, critical section 에서의 작업이 context switching 보다 더 빨리 끝난다면 스핀락이 뮤텍스보다 더 효율적일 수도 있음.
Semaphore
멀티프로그래밍 환경에서 다수의 프로세스/스레드의 여러 개의 공유 자원에 대한 접근을 제한하는 동기화 기법
signal machanism 을 가진, 하나 이상의 프로세스/스레드가 critical section 에 접근 가능하도록 하는 장치
- wait() 와 signal() 을 이용하여 작업의 순서를 정해줄 수 있음.
- signal() 과 wait() 가 같은 스레드에서 실행될 필요는 없다.
- value 값으로 다양한 값을 가질 수 있으며
value 값이 1인 세마포 (= binary semaphore 이진 세마포) : 하나의 스레드만 critical section 접근 가능하도록.
value > 1 인 경우 counting semaphore.
Mutex vs. Semaphore
뮤텍스는 락을 가진 스레드/프로세스만 락을 해제할 수 있지만 세마포는 어느 스레드에서 signal()을 날리고 어디서 wait()를 날릴 지 알 수 없다. (세마포는 여러 스레드가 동시에 접근할 수 있다는 차이)
→ 상호 배제(mutual exclusion)만 필요하다면 뮤텍스를, 작업 간의 실행 순서 동기화가 필요하다면 세마포를 권장
Mutex | - 여러 스레드를 사용하는 환경에서 자원에 대한 접근을 강제하기 위한 동기화 매커니즘 - Boolean 타입의 Lock 변수를 사용 - 공유자원을 사용중인 스레드가 있을 때, 다른 스레드가 공유자원에 접근한다면 Blocking 후 대기 큐로 보낸다. - Lock을 건 스레드만 Lock을 해제할 수 있다. |
Spinlock | - 기본적으로 Mutex 와 유사 - Busy-waiting 하며 대기 큐를 갖지 않는다 |
Semaphore | - semaphore 변수를 통해 wait, signal을 관리한다. semaphore 변수는 0 이상의 정수형 변수를 갖는다. - 접근 가능한 공유 자원의 수가 1개일 때는 이진 세마포어로 뮤텍스처럼 사용할 수 있다. - lock() 를 걸지 않은 스레드도 signal()을 보내 해제할 수 있다. |
ex) 식당 줄서기.
자리 하나 뿐인 식당
- 스핀락 : 문앞에서 자리 있냐고 계속 물어보기
- 뮤텍스 : 대기실에 이동했다가 자리 나면 들어오기
자리 n개인 식당
- 세마포어 : 식당 들어오면 wait() 나갈 때 signal() 날리기. n개 이상으로 사람 오면 위 두가지 방법 중 하나로 기다리기.
'컴퓨터시스템' 카테고리의 다른 글
네이밍 컨벤션 - camelCase, PascalCase, snake_case, kebab-case (0) | 2022.09.14 |
---|---|
Context Switching 이란? (0) | 2022.09.05 |
thread란? + 멀티쓰레드의 장단점 (0) | 2022.05.13 |
네트워크 기초 (0) | 2022.01.06 |
[네트워크] 네트워크 패킷 분석 및 Wireshark 설치 (mac) (0) | 2022.01.06 |