본문 바로가기
혼자 공부하는 것들/운영체제

[운영체제] Race Condition, Mutual Exclusive(상호배제) 실습

by applepick 2020. 10. 2.
반응형

 

Race Condition이란?

두 개 이상의 프로세스가 공통 자원을 병행적으로(concurrently) 읽거나 쓰는 동작을 할 때, 공용 데이터에 대한 접근이 어떤 순서에 따라 이루어졌는지에 따라 그 실행 결과가 같지 않고 달라지는 상황을 말한다. Race의 뜻 그대로, 간단히 말하면 경쟁하는 상태, 즉 두 개의 스레드가 하나의 자원을 놓고 서로 사용하려고 경쟁하는 상황을 말한다.

 

Mutual Exclusive이란?

상호 배제라는 뜻으로 는 동시 프로그래밍에서 공유 불가능한 자원의 동시 사용을 피하기 위해 사용되는 알고리즘으로, 임계 구역(critical section)으로 불리는 코드 영역에 의해 구현된다.

공유 불가능한 자원의 예로는 동시에 실행되고 있는 프로그램간의 통신에 사용되는 비트 단위의 깃발, 계수기,  등이다. 문제는 스레드가 언제라도 정지되거나 시작될 수 있다는 것이다.


상호배제를 한 코드와 하지않은 코드를 같이 실습하면서 어떠한 상황인지 알아보자.

 

race-thread.c 코드

#define ITER (50000000) 
#include <pthread.h> 
#include <stdio.h> 
int gvar = 0;  //<===공유자원
void * X(void *i); 
int main(void) 
{ 
 	pthread_t t1; 
 	pthread_attr_t attr; 
 	void *status; 
 	int j; 
 	pthread_attr_init(&attr); 
 	pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); 
 	pthread_create(&t1, &attr, X, NULL); 
 	// Main thread 
 	///////////////////////// 
 	for (j = 0; j < ITER; j++) { 
 	gvar = gvar + 1; 
 	} 
 	///////////////////////// 
 	pthread_join(t1, &status); 
 	printf("%d₩n", gvar); 
	} 
void * X(void *i) 
{ 
 	int j; 
 	// Child thread 
 	///////////////////////// 
 	for (j = 0; j < ITER; j++) { 
 	gvar = gvar + 1; 
 	} 
 	///////////////////////// 
 	pthread_exit(NULL); 
} 

컴파일 코드

gcc -o race-thread race-thread.c -lpthread 
./race-thread & 

1. 실행하면 몇 개의 스레드가 수행되는가?

- 2개

2. 각 스레드에서 “ gvar = gvar + 1; ” 은 몇 번씩 수행되는가? 

(결국 각 스레드별로 gvar 값을 얼마를 증가시키게 되는가?) 

- 5천만번정도 실행된다.  50544581값이된다.

3. 모든 스레드가 증가시킨 총 합은 얼마인가? 프로그램이 마지막으로 출력한 gvar 값과 일치하는가? 일치하지 않는다면 그 이유는 무엇인가? 

- 모든 합은 1억이 된다. 출력과 일치하지 않는 이유는 레이스 컨디션이 발생되기 때문이다. gvar 자원을 공유하고있기때문이다.


이제 Mutual Exclusive(상호배제)를 적용한 코드를 분석해보자.

 

me-thread.c 코드

#define ITER (50000000)
#include <pthread.h>
#include <stdio.h>
int gvar = 0;
void * X(void *i);
pthread_mutex_t m;
int main(void)
{
 	pthread_t t1;
 	pthread_attr_t attr;
 	void *status;
 	int j;
 	pthread_attr_init(&attr);
 	pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
 	pthread_create(&t1, &attr, X, NULL);
 	// Main thread
 	/////////////////////////
 	for (j = 0; j < ITER; j++) {
 		pthread_mutex_lock(&m);
 		gvar = gvar + 1;
 		pthread_mutex_unlock(&m);
 	}
 	/////////////////////////
 	pthread_join(t1, &status);
 	printf("%d\n", gvar);
}
void * X(void *i)
{
	 int j;
	 // Child thread
 	/////////////////////////
 	for (j = 0; j < ITER; j++) {
 		pthread_mutex_lock(&m);
 		gvar = gvar + 1;
 		pthread_mutex_unlock(&m);
 	}
 	/////////////////////////
 	pthread_exit(NULL);
}

1. 실행하면 몇 개의 스레드가 수행되는가?

-2개의 스레드 수행

 

2. 각 스레드에서 “ gvar = gvar + 1; ” 은 몇 번씩 수행되는가?

-50000000번 수행한다.

(결국 각 스레드별로 gvar 값을 얼마를 증가시키게 되는가?)

각 스레드별로 50000000번 증가된다.

 

3. 모든 스레드가 증가시킨 총 합은 얼마인가?

 프로그램이 마지막으로 출력한 gvar 값과 일치하는가?

100000000이 된다. 일치한다. 

 

4. 앞서 실습한 race-thread 프로그램과 비교해보시오. 어떤 부분이 달라졌는가?

- 앞서 실습한 race-thread는 증가부분이 중복이 되었지만, 이번실습에서는 중복이되지않는다. 

 

5. 프로그램에서 Critical region에 해당하는 부분을 적으시오.

 - gvar = gvar + 1;이부분에서 critical region이 발생된다.

 

★중요!

6. Critical region에 한 순간에 1개의 스레드만 수행될 수 있게 하기 위해 어떤 것(함수)을

사용하고 있는가?

- 각 메인과 자식 스레드에 코드를 보면 

        pthread_mutex_lock(&m);

        gvar = gvar + 1;

        pthread_mutex_unlock(&m);

이부분으로인해 크리티컬리전이 한순간에 한개만 수행된다. 한 쪽을 잠구고 한쪽에서 실행하고 다른부분도 마찬가지로 이렇게 수행하다보니 값이 중복이되지않게 된다.

반응형

댓글