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
'Programming > Network' 카테고리의 다른 글
열혈 TCP/IP 19-1. 커널오브젝트(Kernel Objects) (0) | 2021.04.11 |
---|---|
열혈 TCP/IP 18-5. 쓰레드의 소멸과 멀티쓰레드 기반의 다중접속 서버의 구현 (0) | 2021.03.28 |
열혈 TCP/IP 18-3. 쓰레드의 문제점과 임계영역(Critical Section) (0) | 2021.03.28 |
열혈 TCP/IP 18-2. 쓰레드의 생성 및 실행 (0) | 2021.03.28 |
열혈 TCP/IP 18-1. 쓰레드의 이론적 이해 (0) | 2021.03.28 |