728x90

동기화

- 임계 영역을 하나의 쓰레드만 실행 가능하도록 제한하는 것

- 동일한 메모리 영역에 접근하는 쓰레드의 실행 순서를 지정

- 동기화 기법 : 뮤텍스, 세마 포어

 

뮤텍스 기반의 동기화

- 임계영역에 접근하는 열쇠로 비유

- 뮤텍스 생성과 소멸

int pthread_mutex_init(pthread_mutex_t *m, const pthread_mutexattr_t *a);
int pthread_mutex_destroy(pthread_mutex_t *m);

- 뮤텍스 획득과 반환

     -> 하나의 쓰레드가 lock을 호출하면 다른 함수는 대기하고 있다가 unlock되고 대기하고 있던 쓰레드가 lock을 호출하면서 실행

int pthread_mutex_lock(pthread_mutex_t *m);
int pthread_mutex_unlock(pthread_mutex_t *m);

- lock을 너무 많이 호출하게 되면 성능에 저하가 일어날 수 있음

#define NUM_THREAD	100
long long num=0;
pthread_mutex_t mutex;

int main(int argc, char *argv[]) 
{
	pthread_t thread_id[NUM_THREAD];
	int i;
	
	pthread_mutex_init(&mutex, NULL);		// 뮤텍스 생성

	for(i=0; i<NUM_THREAD; i++)
	{
		if(i%2)
			pthread_create(&(thread_id[i]), NULL, thread_inc, NULL);
		else
			pthread_create(&(thread_id[i]), NULL, thread_des, NULL);	
	}	

	for(i=0; i<NUM_THREAD; i++)
		pthread_join(thread_id[i], NULL);	// 쓰레드 종료 대기

	printf("result: %lld \n", num);
	pthread_mutex_destroy(&mutex);			// 뮤텍스 소멸
	return 0;
}

void * thread_inc(void * arg) 
{
	int i;
	pthread_mutex_lock(&mutex);				// 뮤텍스 lock
	for(i=0; i<50000000; i++)
		num+=1;
	pthread_mutex_unlock(&mutex);			// unlock
	return NULL;
}
void * thread_des(void * arg)
{
	int i;
	for(i=0; i<50000000; i++)
	{
		pthread_mutex_lock(&mutex);			// 뮤텍스 lock
		num-=1;
		pthread_mutex_unlock(&mutex);		// unlock	
	}
	return NULL;
}

 

세마포어 기반의 동기화

- 임계영역에 접근할 쓰레드의 수를 제한하는 방법

- 세마포어의 생성과 소멸

    -> pshread : 0 이외 값 전달 시 둘 이상의 프로세스에 접근 가능한 세마포어가 생성

    -> value : 세마포어 카운트 값

int sem_init(sem_t * sem, int pshared, unsigned int value);
int sem_destroy(sem_t *sem);

- 세마포어 획득과 반환

int sem_post(sem_t *sem);
int sem_wait(sem_t *sem);

- 두 세마포어로 임계영역 및 실행순서 동기화

    -> 세마포어 카운트를 조절하면서 먼저 scanf가 먼저 일어나고 += 연산이 일어나게 순서를 조절

void * read(void * arg);
void * accu(void * arg);
static sem_t sem_one;
static sem_t sem_two;
static int num;

int main(int argc, char *argv[])
{
	pthread_t id_t1, id_t2;
	sem_init(&sem_one, 0, 0);
	sem_init(&sem_two, 0, 1);

	pthread_create(&id_t1, NULL, read, NULL);
	pthread_create(&id_t2, NULL, accu, NULL);

	pthread_join(id_t1, NULL);
	pthread_join(id_t2, NULL);

	sem_destroy(&sem_one);
	sem_destroy(&sem_two);
	return 0;
}

void * read(void * arg)
{
	int i;
	for(i=0; i<5; i++)
	{
		fputs("Input num: ", stdout);

		sem_wait(&sem_two);		// sem_two 열쇠 감소(count : 1 -> 0)
		scanf("%d", &num);
		sem_post(&sem_one);		// sem_one 열쇠를 하나 줌(count : 0 -> 1)
	}
	return NULL;	
}
void * accu(void * arg)
{
	int sum=0, i;
	for(i=0; i<5; i++)
	{
		sem_wait(&sem_one);		// sem_one 열쇠 감소(count : 1 -> 0)
		sum+=num;
		sem_post(&sem_two);		// sem_two 열쇠를 하나 줌(count : 0 -> 1)
	}
	printf("Result: %d \n", sum);
	return NULL;
}

 

728x90

+ Recent posts