Archieve/OS(18)
-
동기화 (4) Race
경쟁(Race)는 프로그램의 정확성이 다른 쓰레드가 포인트 y에 도달하기 전에 제어 흐름에서 한 쓰레드가 포인트 x에 도달하는 것에 의존할 때 발생한다. 예제를 사용하면 레이스의 본질을 이해하기 쉽다. 아래 코드에서는 4 개의 피어 쓰레드를 생성하고 고유한 정수 ID의 포인터를 각각의 쓰레드에 넘겨준다. #include #include #include #define N 4 void *thread(void *vargp); int main() { pthread_t tid[N]; int i; for (i = 0; i < N; i++)// Line 11 pthread_create(&tid[i], NULL, thread, &i);// Line 12 for (i = 0; i < N; i++) pthread_join..
2022.12.07 -
동기화 (3) Thread Safety
쓰레드를 활용하여 프로그래밍을 수행할 때 쓰레드 안전성이라고 부르는 특성을 가지는 함수를 작성하도록 유의해야 한다. 어떤 함수는 다수의 동시성 쓰레드로부터 반복적으로 호출될 경우 항상 정확한 결과를 만드는 경우에만 Thread Safety 라고 부른다. 만일 어떤 함수가 이를 충족하지 못하는 상태라면 이를 Thread-unsafe 하다고 표현한다. Thread-unsafe한 4가지 클래스를 정의하면 다음과 같다. 클래스 1: 공유 변수를 보호하지 않는 함수들. 직전 글에서 볼 수 있듯, 쓰레드 함수 내에서의 공유 변수 접근을 보호하지 못한다면 동기화 오류가 발생할 수 있다. 세마포어 연산 P와 V를 활용하여 Thread-safety한 쓰레드 함수로 개선할 수 있다. unsigned int next = 1..
2022.12.07 -
동기화 (2) 세마포어
동시성 프로그래밍의 개척자인 다익스트라는 서로 다른 실행 쓰레드를 동기화하는 문제에 대한 고전적인 해답을 세마포어라고 부르는 특별한 타입의 변수에 기초하여 제안하였다. 세마포어 s는 음수가 아닌 정수 값을 갖는 전역 변수로 두 개의 특별한 연산인 P와 V를 통해서만 조작이 가능하다. P(s): s가 0이 아닌 경우, P는 s를 감소시키고 즉시 리턴한다. 만일 s가 0이라면 쓰레드는 s가 0이 아닌 양의 정수가 될 때까지 기다렸다가, 이후 V 연산에 의해 s가 갱신된 이후에서야 다시 재시작한다. 재시작 이후에 P는 s를 감소시키고 제어권을 다시 호출자에게 돌려준다. V(s): V 연산은 s를 1 증가시킨다. 직전의 설명한 P의 반대라고 생각할 수 있다. P에서 테스트와 감소 연산은 일단 세마포어 s가 0이..
2022.12.07 -
동기화 (1)
쓰레드 메모리 모델 동시성 쓰레드의 풀은 한 개의 컨텍스트에서 돌아간다. 각각의 쓰레드는 자신만의 별도의 쓰레드 컨텍스트를 가지며, 여기에는 쓰레드 ID, 스택, 스택 포인터, 프로그램 카운터, 조건 코드, 범용 레지스터 값이 포함될 것이다. 각 쓰레드는 프로세스의 가상주소공간을 공유하며 여기에는 코드 섹션, 데이터 섹션, 힙, 공유 라이브러리 코드 등을 포함할 것이다. 각 쓰레드는 별도의 스택 저장소를 가지고 있으며 때문에 한 쓰레드가 다른 쓰레드의 스택에 접근하여 이를 읽거나 쓰는 등의 행동은 불가능하다. 또한 각자 고유한 레지스터를 참조하고 있기 때문에 다른 쓰레드의 레지스터에 접근하여 읽고 쓰는 것도 불가능해진다. 마지막으로 쓰레드들은 각자 고유한 PC 값을 가지고 분리된 형태의 논리 흐름으로 전..
2022.12.07 -
쓰레드
동시성 논리 흐름을 생성하는 대표적인 방법으로 크게 3 가지가 존재한다. 먼저, 각각의 흐름에 대해 별도의 프로세스를 생성하는 프로세스 기반 동시성 프로그래밍이 있다. 커널은 각각의 프로세스를 자동으로 스케쥴링하여 각 프로세스는 자신만의 고유한 사적 주소공간을 가지며 이로 인해 흐름들이 데이터를 공유하기가 어려워진다. 두 번째 방법으로 우리 자신의 논리흐름을 생성하고 명시적으로 이 흐름들을 스케쥴링하기 위해 I/O 다중화를 이용한다. 이 경우 단 하나의 프로세스만이 존재하기 때문에 흐름들은 전체 주소공간을 공유한다. 해당 글에서는 동시성 프로그래밍을 수행하기 위한 세 번째 방법인 쓰레드라는 개념을 소개하고자 한다. 쓰레드는 프로세스의 컨텍스트 내에서 돌아가는 논리 흐름이다. 앞서 프로세스를 설명하는 글에..
2022.12.07 -
프로세스를 이용한 동시성 프로그래밍
동시성 프로그램을 만드는 가장 간단한 방법은 프로세스를 사용하는 것이며, fork, exec, waitpid와 같은 친숙한 함수를 활용하여 주로 구현된다. 예를 들어 동시성 서버를 구현하는 자연스러운 방법은 부모에서 클라이언트 연결 요청을 수락하여, 이후 새로운 자식 프로세스를 생성하여 각각의 새로운 클라이언트를 서비스하는 것이 있다. 이것이 어떻게 동작하는지 알아보기 위해 두 개의 클라이언트와 listen 식별자에서 연결 요청을 기다리는 하나의 서버가 있다고 가정하자. 연결 요청을 서버가 수락하게 되면 해당 그림의 connfd(4) 처럼 연결 요청을 수락하게 된다. 서버는 자식을 fork 하고, 자식은 서버의 식별자 테이블 사본 전체를 가져오게 된다. 자식은 listenfd(3)의 자신의 사본을 닫고 ..
2022.12.07