1. 병행성: 개요
- 멀티 쓰레드 프로그램은 하나 이상의 실행 지점(독립적으로 불러 들여지고 실행될 수 있는 여러 개의 PC 값)을 가지고 있다.
- 멀티 쓰레드를 이해하는 다른 방법은 각 쓰레드가 프로세스와 매우 유사하지만, 차이가 있다면 쓰레드들은 주소 공간을 공유하기 때문에 동일한 값에 접근할 수 있다는 것이다.
- 쓰레드는 어디서 명령어들을 불러 들일지 추적하는 프로그램 카운터(PC)와 연산을 위한 레지스터들을 가지고 있다.
- 두 개 이상의 쓰레드가 하나의 프로세서에서 실행 중이라면 문맥 교환이 이루어져야 한다.
- 문맥 전환을 할 때 프로세스는 자신의 상태를 프로세스 제어 블럭(process control block, PCB)에 저장하듯이 쓰레드는 쓰레드 제어 블럭(thread control block, TCB)에 저장한다.
- 가장 큰 차이 중 하나는 프로세스의 경우와 달리 쓰레드 간의 문맥 교환에서는 주소 공간을 그대로 사용한다.
- 쓰레드와 프로세스의 또 다른 차이는 쓰레드는 자신만의 스택이 존재한다.
1.1 왜 쓰레드를 사용하는가?
- 쓰레드를 사용해야하는 2가지 주요 이유가 있다.
- 병렬 처리(parallelism)
- 느린 I/O로 인해 프로그램 실행이 멈추지 않도록하기 위해 쓰레드를 사용한다.
쓰레드는 병렬처리가 가능한데 문맥전환을 한다…?! 이 말의 뜻은 만약 프로세서가 1개일 때는 쓰레드가 문맥전환을 이룬다 <- 이것도 멀티 프로세스보다 성능이 좋은데 그 이유는 문맥전환의 비용이 쓰레드가 더 적기 때문이다.
2번의 추가 예로는 예를들어 한 프로세스에서 파일 입출력 시그널이 발생했다. 원래 같으면 해당 프로세스는 블록되고 다른 프로세스로 제어가 넘어가야한다. 하지만 멀티 쓰레드라면 파일 입출력이 진행 되는 동안 같은 프로세스에서 다른 쓰레드가 다른 작업을 이어 나갈 수 있다.
1.2 예제: 쓰레드 생성
- 위의 코드를 실행하면, A B 또는 B A가 출력된다.
- 생성된 쓰레드는 호출자와는 별개로 실행된다는 것을 확인할 수 있다.
- 다음에 실행될 쓰레드는 OS 스케줄러(scheduler)에 의해 결정된다.
1.3 훨씬 더 어려운 이유: 데이터의 공유
- 위의 코드를 실행하면 출력으로 20000000이 나올 줄 알았지만, 결과는 매번 다르다. ex) 187777789, 15796892
- 왜 이런 결과가 나오는지 궁금하다면 더 읽어보자!
1.4 문제의 핵심: 제어 없는 스케줄링
- mythread 함수의 for문을 역 어셈블리 하면 위와 같은 결과를 가진다.
- 위의 영역을 두 쓰레드가 동시에 접근하기 때문에 결과가 달라지는 것이다.
- 명령어의 실행 순서에 따라 결과가 달라지는 상황을 경쟁 조건(race condition) 혹은 데이터 경쟁(data race)라고 한다.
- 멀티 쓰레드가 같은 코드를 실행할 때 경쟁 조건이 발생하기 때문에 이러한 코드 부분을 임계 영역(critical section)이라고 부른다.
- 공유 변수(공유 자원)을 접근하고 하나 이상의 쓰레드에서 동시에 실행되면 안 되는 코드를 임계 영역이라 부른다.
- 이러한 코드에서 필요한 것은 상호 배제(mutual exclusion)이다.
- 이 속성은 하나의 쓰레드가 임계 영역 내의 코드를 실행 중일 때는 다른 쓰레드가 실행할 수 없도록 보장해준다.
1.5 원자성에 대한 바람
- 임계 영역 문제에 대한 해결 방법 중 하나로 강력한 명령어 한 개로 의도한 동작을 수행하여, 인터럽트 발생 가능성을 원천적으로 차단하는 것이다.
- 락과 같은 기능을 사용한다.
- 우리가 대신 해야 할 일은 하드웨어 동기화 함수(synchronization primitives) 구현에 필요한 몇 가지 유용한 명령어를 요청하는 것이다.
댓글남기기