다음 그림과 보기를 참고해 1, 3번 문제의 빈칸을 채우고 2번 문제에 답해주세요.
<보기>
경쟁 상황(race condition)
,
동기화
,프로세스
,조작
,진행
,조정
증가
,감소
4
,5
,6
,count
-
두 개의 프로세스 생산자와 소비자 프로세스는 각각 count++와 count--를 수행합니다. count라는 변수는 버퍼에 새 항목을 추가할 때마다
_____
되고 버퍼에서 한 항목을 꺼낼 때마다_____
되는 것으로, 현재 count는 5입니다. 다음 그림에서 register1과 register2는 한 CPU만 접근할 수 있는 로컬 레지스터 중 하나입니다. count++와 count-- 코드를 병행하여 실행해 아래처럼 count가_____
이/가 되었습니다. (빈칸채우기) -
count 값이 정확한가요? 정확하지 않다면 실제로는 몇 개의 버퍼가 채워져 있어야하며 왜 부정확한지 설명해주세요. (주관식)
-
__________
이란 실행 결과가 접근이 발생한 특정 순서에 의존하는 상황입니다.__________
으로부터 보호하기 위해 한순간에 하나의 프로세스만이 변수_____
를 조작하도록 보장해야하며, 이를 위해 프로세스들이_____
되록 할 필요가 있습니다. (빈칸채우기)
📄 답지
다음 그림과 보기를 참고해 1, 3번 문제의 빈칸을 채우고 2번 문제에 답해주세요.
<보기>
경쟁 상황(race condition)
,
동기화
,프로세스
,조작
,진행
,조정
증가
,감소
4
,5
,6
,count
-
두 개의 프로세스 생산자와 소비자 프로세스는 각각 count++와 count--를 수행합니다. count라는 변수는 버퍼에 새 항목을 추가할 때마다
증가
되고 버퍼에서 한 항목을 꺼낼 때마다감소
되는 것으로, 현재 count는 5입니다. 다음 그림에서 register1과 register2는 한 CPU만 접근할 수 있는 로컬 레지스터 중 하나입니다. count++와 count-- 코드를 병행하여 실행해 아래처럼 count가4
이/가 되었습니다. (빈칸채우기)증가, 감소, 4
-
count 값이 정확한가요? 정확하지 않다면 실제로는 몇 개의 버퍼가 채워져 있어야하며 왜 부정확한지 설명해주세요. (주관식)
count++와 count--를 병행하게 실행하는 것은 해당 문장들을 임의의 순서로 뒤섞어 순차적으로 실행하는 것과 동일합니다. 따라서 count는 실행 순서에 따라 4나 6의 부정확한 값을 갖게되며 실제로는 5개의 버퍼가 채워져 있습니다. 이는 두 개의 프로세스가 동시에 변수 count를 조작하도록 허용했기 때문입니다.
-
경쟁 상황(race condition)
이란 실행 결과가 접근이 발생한 특정 순서에 의존하는 상황입니다.경쟁 상황
으로부터 보호하기 위해 한순간에 하나의 프로세스만이 변수count
를 조작하도록 보장해야하며, 이를 위해 프로세스들이동기화
되록 할 필요가 있습니다. (빈칸채우기)경쟁 상황, 경쟁 상황, count, 동기화
-
각 프로세스는 _____ 이라고 부르는 코드 부분을 포함하고 있고 그 안에서는 적어도 하나 이상의 다른 프로세스와 공유하는 데이터에 접근하고 갱신할 수 있다.
-
_______는 프로세스들이 데이터를 협력적으로 공유하기 위하여 자신들의 활동을 동기화할 때 시용할 수 있는 프로토콜을 설계하는 것이다.
-
임계구역 문제를 해결하기 위해서는 다음 세가지 요구 조건을 충족시켜야 한다.
- ________: 임계구역에는 동시에 한 프로세스만 접근가능함
- ________: 유한한 시간 내에 임계구역에 들어갈 프로세스를 정해야함
- ________: 프로세스가 임계구역을 들어가기 위한 요청 이후 실제 진입까지의 과정이 유한한 시간내에 일어나야함
📄 답지
-
각 프로세스는 _____ 이라고 부르는 코드 부분을 포함하고 있고 그 안에서는 적어도 하나 이상의 다른 프로세스와 공유하는 데이터에 접근하고 갱신할 수 있다. 임계구역 (critical section)
-
_______는 프로세스들이 데이터를 협력적으로 공유하기 위하여 자신들의 활동을 동기화할 때 시용할 수 있는 프로토콜을 설계하는 것이다. 임계구역 문제
-
임계구역 문제를 해결하기 위해서는 다음 세가지 요구 조건을 충족시켜야 한다.
- ________: 임계구역에는 동시에 한 프로세스만 접근가능함
- ________: 유한한 시간 내에 임계구역에 들어갈 프로세스를 정해야함
- ________: 프로세스가 임계구역을 들어가기 위한 요청 이후 실제 진입까지의 과정이 유한한 시간내에 일어나야함 (스케쥴링에서 기아문제같은것이 일어나지 않는것을 말하는 듯) 상호 배제(Mutual Exclusion) 진행(Progress) 한정된 대기(Bounded Waiting)
📄 답지
피터슨의 해결법은 들어가길 원하는지 표시하는 flag
와 차례인지 표시하는 turn
을 동시에 써서 임계구역 문제 해결을 위한 3가지 요구조건인 1.상호배제
2.진행
3.유한대기
의 조건을 모두 만족시킵니다.
busy waiting
으로 자원 낭비.
busy waiting
이란 대기를 하는 동안 실제로 하는 일은 없는데 CPU를 계속 사용하며 대기하는 것으로, spin lock이라고도 한다.
데이터 무결성 문제를 일으킬 수 있음 / 상호배제 조건 미달
현대적인 아키텍쳐에서는 성능 향상을 위해 작업 순서를 바꿀 수 있기 때문에
다중스레드가 데이터를 공유하는 과정에서 실행할 명령어들의 순서를 바꿔버리면 상호배제 조건이 충족되지 않음.
-
Mutex lock는 특정 코드 영역의 쓰레드를 실행할 때 한번에 하나 이상의 쓰레드만 실행 가능하도록 하는 방법이다. (O / X)
-
아래의 코드 결과는 서술하시오.
// exam2.c
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int g_count = 0; // 쓰레드 공유자원.
void *t_function(void *data)
{
int i;
char* thread_name = (char*)data;
// critical section
g_count = 0; // 쓰레드마다 0부터 시작.
for (i = 0; i < 3; i++)
{
printf("%s COUNT %d\n", thread_name, g_count);
g_count++; // 쓰레드 공유자원, 1증가.
sleep(1);
}
}
int main()
{
pthread_t p_thread1, p_thread2;
int status;
pthread_create(&p_thread1, NULL, t_function, (void *)"Thread1");
pthread_create(&p_thread2, NULL, t_function, (void *)"Thread2");
pthread_join(p_thread1, (void *)&status);
pthread_join(p_thread2, (void *)&status);
}
// compile
// gcc exam2.c -o exam2
- 아래의 코드 결과를 서술하시오
// exam3.c
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
// 뮤텍스 객체 선언
pthread_mutex_t mutex_lock;
int g_count = 0; // 쓰레드 공유자원.
void *t_function(void *data)
{
int i;
char* thread_name = (char*)data;
pthread_mutex_lock(&mutex_lock);
// critical section
g_count = 0; // 쓰레드마다 0부터 시작.
for (i = 0; i < 3; i++)
{
printf("%s COUNT %d\n", thread_name, g_count);
g_count++; // 쓰레드 공유자원
sleep(1);
}
pthread_mutex_unlock(&mutex_lock);
}
int main()
{
pthread_t p_thread1, p_thread2;
int status;
// 뮤텍스 객체 초기화, 기본 특성으로 초기화 했음
pthread_mutex_init(&mutex_lock, NULL);
pthread_create(&p_thread1, NULL, t_function, (void *)"Thread1");
pthread_create(&p_thread2, NULL, t_function, (void *)"Thread2");
pthread_join(p_thread1, (void *)&status);
pthread_join(p_thread2, (void *)&status);
}
// compile
// gcc exam3.c -o exam3 -lpthread
Mutex 코드 참고(문제 다 풀고 들어가세요) https://bitsoul.tistory.com/172
📄 답지
- Mutex lock는 특정 코드 영역의 쓰레드를 실행할 때 한번에 하나 이상의 쓰레드만 실행 가능하도록 하는 방법이다. (O / X)
- 정답 : X , 한번에 하나의 쓰레드만 실행 가능하도록 하는 방법이다.
- 아래의 코드 결과는 서술하시오.
// exam2.c
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int g_count = 0; // 쓰레드 공유자원.
void *t_function(void *data)
{
int i;
char* thread_name = (char*)data;
// critical section
g_count = 0; // 쓰레드마다 0부터 시작.
for (i = 0; i < 3; i++)
{
printf("%s COUNT %d\n", thread_name, g_count);
g_count++; // 쓰레드 공유자원, 1증가.
sleep(1);
}
}
int main()
{
pthread_t p_thread1, p_thread2;
int status;
pthread_create(&p_thread1, NULL, t_function, (void *)"Thread1");
pthread_create(&p_thread2, NULL, t_function, (void *)"Thread2");
pthread_join(p_thread1, (void *)&status);
pthread_join(p_thread2, (void *)&status);
}
// compile
// gcc exam2.c -o exam2
- 정답 : Thread1, 2 모두 g_count 쓰레드 자원을 공유하기 때문에 매번 exam2를 실행할 때 마다 이상한 값이 나온다.
- 아래의 코드 결과를 서술하시오
// exam3.c
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
// 뮤텍스 객체 선언
pthread_mutex_t mutex_lock;
int g_count = 0; // 쓰레드 공유자원.
void *t_function(void *data)
{
int i;
char* thread_name = (char*)data;
pthread_mutex_lock(&mutex_lock);
// critical section
g_count = 0; // 쓰레드마다 0부터 시작.
for (i = 0; i < 3; i++)
{
printf("%s COUNT %d\n", thread_name, g_count);
g_count++; // 쓰레드 공유자원
sleep(1);
}
pthread_mutex_unlock(&mutex_lock);
}
int main()
{
pthread_t p_thread1, p_thread2;
int status;
// 뮤텍스 객체 초기화, 기본 특성으로 초기화 했음
pthread_mutex_init(&mutex_lock, NULL);
pthread_create(&p_thread1, NULL, t_function, (void *)"Thread1");
pthread_create(&p_thread2, NULL, t_function, (void *)"Thread2");
pthread_join(p_thread1, (void *)&status);
pthread_join(p_thread2, (void *)&status);
}
// compile
// gcc exam3.c -o exam3 -lpthread
- 정답 : Mutex Lock이 걸려서 Thread1이 먼저 실행된다면 Thread2는 1이 끝날 때 까지 임계영역에 들어가 수 없기 때문에 count 0 1 2를 출력하고 그 다음 Thread2의 count가 0 1 2 를 출력한다. 만약 Thread2가 먼저 실행된다면 앞에 설명한 것과 반대로 출력된다.
Mutex 코드 참고 https://bitsoul.tistory.com/172
- [1-1] 다음중 세마포의 정의로 가장 적절한 것은?
- a. '세'초가 '마'싯는거 '포'기함
- b. 순차적으로 리소스에 접근 허용이 가능한 개수를 의미하는 정수 변수
- c. 동시에 리소스에 접근 허용이 가능한 개수를 의미하는 실수 변수
- d. 동시에 리소스에 접근 허용이 가능한 개수를 의미하는 정수 변수
- [1-2] 다음 중 세마포에서 가능한 모든 연산에 해당하는 것은? (단, 초기화 제외)
- a. eat(), pray(), love()
- b. love(), sick(), girl()
- c. signal(), twice()
- d. wait(), signal()
<보기>
S > 0 S >= 0 S < 0 S <= 0 S == 0 S++; S--;
-
[2-1] 보기에서 아래 내용에 해당되는 적절한 범위를 골라주세요
- 새로운 스레드가 임계영역(Critical Section)에 진입할 수 없는 범위 :
- 새로운 스레드가 임계영역(Critical Section)에 진입할 수 있는 범위 :
- 새로운 스레드가 임계영역(Critical Section)에 진입할 수 없는 범위 :
-
[2-2] 보기에서 💙(a)와 (b)💙에 들어갈 적절한 수식을 골라주세요
wait(S) {
while (💙(a)💙)
; //busy wait
S--;
}
// P(S) : S값 검사 (공유자원을 획득하기 위한 과정)
signal(S) {
💙(b)💙;
}
// V(S) : S값 증가 (공유자원을 다 사용하고 나서 반납하는 과정)
- 다음 설명을 읽고 적절한 세마포 종류를 적어주세요(단답식, 1등 +50점)
- 0과 1의 값만 가능해서, 쿠키교수님께서 설명해주신 'Mutex락'과 유사하게 동작하는 세마포어 :
ㅇㅇ 세마포어(...... semaphores)
- 영역(domain)에 제한이 없어 총 가용한 자원의 개수로 초기화되는 세마포어 :
ㅇㅇㅇ 세마포어(........ semaphorse)
- 0과 1의 값만 가능해서, 쿠키교수님께서 설명해주신 'Mutex락'과 유사하게 동작하는 세마포어 :
✨스핀락(Spin Lock)이란?
- 임계구역(Critical Section) 진입이 불가할 때 가능할 때까지 whlie문을 돌면서 재시도하는 방식으로 구현된 락
- OS의 스케줄링 지원을 받지 않기 때문에, 해당 스레드에 대한 문맥교환(Context Switching)이 일어나지 않음
- 만약, 스핀락이 오랜 시간을 소요한다면 바쁜 대기(Busy Waiting) 현상으로 인해 비효율적임
- 만약, 스핀락이 오랜 시간을 소요하지 않는다면 문맥교환(Context Switching)에 따른 오버헤드를 줄일 수 있어서 효율적임
- [4-1] 위 설명을 읽고, 스핀락이 단일 프로세서 시스템에 적합하지 않은 이유를 설명해주세요(+150점)
- 이유 :
- [4-2] 위 설명을 읽고, 스핀락이 다중 처리기 시스템에서는 종종 사용되는 이유를 설명해주세요(+200점)
- 이유 :
📄 답지
- [1-1] 다음중 세마포의 정의로 가장 적절한 것은?
- d. 동시에 리소스에 접근 허용이 가능한 개수를 의미하는 정수 변수
- [1-2] 다음 중 세마포에서 가능한 모든 연산에 해당하는 것은? (단, 초기화 제외)
- d. wait(), signal()
-
[2-2] 보기에서 💙(a)와 (b)💙에 들어갈 적절한 수식을 골라주세요
- 새로운 스레드가 임계영역(Critical Section)에 진입할 수 없는 범위 :
S <= 0
- 새로운 스레드가 임계영역(Critical Section)에 진입할 수 있는 범위 :
S > 0
- 새로운 스레드가 임계영역(Critical Section)에 진입할 수 없는 범위 :
-
[2-2] 보기에서 💙💙💙에 들어갈 적절한 수식을 골라주세요
wait(S) {
while (💙S <= 0💙)
; //busy wait
S--;
}
// P(S) : S값 검사 (공유자원을 획득하기 위한 과정)
signal(S) {
💙S++;💙
}
// V(S) : S값 증가 (공유자원을 다 사용하고 나서 반납하는 과정)
- 다음 설명을 읽고 적절한 세마포 종류를 적어주세요(단답식, 1등 +50점)
- 0과 1의 값만 가능해서, 쿠키교수님께서 설명해주신 'Mutex락'과 유사하게 동작하는 세마포어 :
이진 세마포어(binary semaphores)
- 영역(domain)에 제한이 없어 총 가용한 자원의 개수로 초기화되는 세마포어 :
카운팅 세마포어(counting semaphorse)
- 0과 1의 값만 가능해서, 쿠키교수님께서 설명해주신 'Mutex락'과 유사하게 동작하는 세마포어 :
- [4-1] 위 설명을 읽고, 스핀락이 단일 프로세서 시스템에 적합하지 않은 이유를 설명해주세요(+150점)
- 이유 : 다른 스레드가 Lock을 가지고 있고 그 스레드가 Lock을 풀어주려면 싱글 CPU 시스템에서는 어차피 Context Switching이 일어나야 하기 때문에 스핀락의 장점이 사라지게 됩니다.
- [4-2] 위 설명을 읽고, 스핀락이 다중 처리기 시스템에서는 종종 사용되는 이유를 설명해주세요(+200점)
- 이유 : 하지만 멀티프로세서 시스템에서는 만약 스핀락의 기다리는 시간이 그리 길지 않다면, Busy Waiting을 하는 것이 Context Switching 을 통해 다른 프로세스로 전환되는데 드는 오버헤드보다 작을 것이기 때문에 종종 쓰입니다.
- 모니터 구조는 모니터 안에 항상 하나의 프로세스만이 활성화되도록 보장해준다?! (O / X)
- 모니터를 사용하면 프로그래머들이 동기화 제약조건을 직접 코딩하지 않아도 된다?! (O / X)
모니터는 공유 자원 + 공유 자원 접근함수로 이루어져 있고, 2개의 큐를 가지고 있다. 각각 mutual exclusion(상호배타) 큐, conditional synchronization(조건동기) 큐이다.
- 상호배타 큐는 공유 자원에 하나의 프로세스만 진입하도록 하기 위한 큐이다.
- 조건동기 큐는 이미 공유자원을 사용하고 있던 프로세스가 일시정지 되면서 대기하는 큐이다.
보기 : Signal and wait, Signal 보내, Signal and continue, 찌릿찌릿찌릿찌릿, 난너를원해
-
___(a)___
기법을 사용한 모니터(3) 상황에서, 프로세스P는 프로세스Q가 모니터를 떠날 때까지 기다리거나 또는 다른 조건을 기다린다. -
___(b)___
기법을 사용한 모니터(3) 상황에서, 프로세스Q는 프로세스P가 모니터를 떠날 때까지 기다리거나 또는 다른 조건을 기다린다.
힌트 : 문제2-2에 정답이 숨어있어요
- 세마포는 모니터보다 낮은 수준(혹은 넓은 범위)의 개념이다. 세마포를 사용하여 모니터를 구현할 수 있기 때문이다. 세마포는 본질적으로 카운터일 뿐이다. 모니터는 이진 세마포다.
- 모니터는 공중 화장실과 같다.
- 한 번에 한 사람 만 입장 할 수 있기 때문이다. 다른 사람이 들어오지 못하도록 문을 잠그고 일을 본 다음 떠날 때 잠금을 해제한다.
- 세마포는 자전거 대여소와 같다.
- 자전거 대여소는 정해진 대수의 자전거를 가지고 있다. 자전거를 대여하려고하는데 자전거가 남아있는 경우 자전거를 탈 수 있다. 그렇지 않으면 기다려야한다.
- 누군가 자전거를 반환하면 그때 다른 사람이 자전거를 탈 수 있다.
- 자전거를 타던 사람은 자전거를 다른 사람에게 빌려줄 수 있다. 자전거 대여소는 자전거를 돌려받기만 하면 자전거를 반납하는 사람이 누구인지는 신경 쓰지 않기 때문이다.
출처 : Semaphore vs. Monitors - what's the difference?
📄 답지
- 모니터 구조는 모니터 안에 항상 하나의 프로세스만이 활성화되도록 보장해준다?! (O / X)
- 모니터를 사용하면 프로그래머들이 동기화 제약조건을 직접 코딩하지 않아도 된다?! (O / X)
모니터는 공유 자원 + 공유 자원 접근함수로 이루어져 있고, 2개의 큐를 가지고 있다. 각각 mutual exclusion(상호배타) 큐, conditional synchronization(조건동기) 큐이다.
- 상호배타 큐는 공유 자원에 하나의 프로세스만 진입하도록 하기 위한 큐이다.
- 조건동기 큐는 이미 공유자원을 사용하고 있던 프로세스가 일시정지 되면서 대기하는 큐이다.
정답 : A = wait(), B = signal()
모니터에서는 프로세스가 모니터 안에서 기다릴 수 있도록
Condition Variable
을 사용한다. 이 condition 변수는wait()
와signal()
연산에 의해서만 접근할 수 있다.
wait()
를 호출한 프로세스는 조건동기 큐로 들어가고, 공유자원을 사용하고 있는 다른 프로세스가signal()
을 호출해 줄 때까지 일시 중지된다.참고로 자바는 모니터를 사용하는 대표적인 언어인데, 자바에서 공통자원에 접근하는 함수는 synchronized(), 블락시키는 함수는 wait(), 블락을 해제시키는 함수는 notify() 이다.
보기 : Signal and wait, Signal 보내, Signal and continue, 찌릿찌릿찌릿찌릿, 난너를원해
-
___(a)___
기법을 사용한 모니터(3) 상황에서, 프로세스P는 프로세스Q가 모니터를 떠날 때까지 기다리거나 또는 다른 조건을 기다린다. -
___(b)___
기법을 사용한 모니터(3) 상황에서, 프로세스Q는 프로세스P가 모니터를 떠날 때까지 기다리거나 또는 다른 조건을 기다린다.
정답 : a = Signal and wait, b = Signal and continue
두 기법의 절충안으로서, signal()을 호출한 즉시 P가 모니터를 떠나고 Q가 즉시 재개되도록 모니터를 구현할 수 있다.
힌트 : 문제2-2에 정답이 숨어있어요
정답 : Signal and wait 기법
- 각 모니터마다 mutex라는 세마포가 정의되고 그 초기값은 1이다.
- 프로세스는 모니터로 들어가기전에 wait(mutex)를 실행하고 모니터를 나온 후에 signal(mutex)를실행 해야 한다.
- Signal and wait 기법을 사용해 모니터를 구현한다.
- signal()을 호출한 프로세스는 실행 재개되는 프로세스가 모니터를 떠날 때까지 기다려야하므로 next라는 세마포 큐가 추가로 필요하다. signaling 프로세스는 이 next 큐에서 대기한다.
- next 세마포 큐에서 일시중지 된 프로세스를 카운트하기위해 next_count 라는 변수를 사용한다.
- 이렇게 하면 모니터 안에서의 상호 배제를 보장할 수 있다.
- 세마포는 모니터보다 낮은 수준(혹은 범위)의 개념이다. 세마포를 사용하여 모니터를 구현할 수 있기 때문이다. 세마포는 본질적으로 카운터일 뿐이다. 모니터는 이진 세마포다.
- 모니터는 공중 화장실과 같다.
- 한 번에 한 사람 만 입장 할 수 있기 때문이다. 다른 사람이 들어오지 못하도록 문을 잠그고 일을 본 다음 떠날 때 잠금을 해제한다.
- 세마포는 자전거 대여소와 같다.
- 자전거 대여소는 정해진 대수의 자전거를 가지고 있다. 자전거를 대여하려고하는데 자전거가 남아있는 경우 자전거를 탈 수 있다. 그렇지 않으면 기다려야한다.
- 누군가 자전거를 반환하면 그때 다른 사람이 자전거를 탈 수 있다.
- 자전거를 타던 사람은 자전거를 다른 사람에게 빌려줄 수 있다. 자전거 대여소는 자전거를 돌려받기만 하면 자전거를 반납하는 사람이 누구인지는 신경 쓰지 않기 때문이다.
출처 : [Semaphore vs. Monitors - what's the difference?](