기본적으로, 복수의 프로세스 및 스레드가 동시동작할 때 발생하는 문제를 해결하기 위함.
자원을 공유하는 병렬 처리 시스템에서 의도하지 않은 데이터 변질이 발생하는 것
교착 상태는, 위의 4가지 조건이 동시에 충족될 때를 말한다.
실행 중인 프로그램(Program). 사용자가 작성한 프로그램이 운영체제에 의해 메모리 공간을 할당받아 실행 중인 상태를 말함.
프로세스보다 작은 실행 단위. 프로세스 내에서 실제로 작업을 수행하는 주체를 의미함. 모든 프로세스 내에는 한 개 이상의 스레드가 존재함. 두 개 이상의 스레드를 가지는 프로세스를 멀티스레드 프로세스 (multi-threaded process)라고 함.
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routinf)(void *), void *arg);
새로운 스레드를 스레드 속성 attr에 따라 생성한다. 스레드 속성 객체 attr이 NULL이라면, 기본 스레드 속성으로 스레드를 생성한다. 스레드가 성공적으로 생성되면 생성된 스레드 ID가 thread에 저장된다. 생성된 스레드는 start_routine arg 인자를 사용하여 실행한다. start_routine이 반환되면, 내부적으로 pthread_exit() 함수가 호출되어 스레드가 종료된다.
int pthread_join(pthread_t thread, void **value_ptr);
스레드 종료를 대기. 대기하는 스레드가 종료되면, value_ptr 인자의 값은 pthread_exit() 함수가 전달한 종료 값을 얻음.
예제
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void *thread(void *vargp);
int main() /* 메인 스레드가 시작되었다 */
{
pthread_t tid; /* 피어 스레드의 스레드ID를 저장하는 데에 쓸 것이다 */
pthread_create(&tid, NULL, thread, NULL); /* 피어 스레드 1개를 생성했다. 이제 메인 스레드와 피어 스레드는 동시에 돌고있다 */
pthread_join(tid, NULL); /* 메인 스레드가 피어 스레드의 종료를 기다린다 */
exit(0); /* 현재 프로세스에 돌고있는 모든 스레드를 종료한다. 현재의 경우, 메인 스레드 1개가 전부다. */
}
void *thread(void *vargp) /* 스레드 루틴을 정의한다 */
{
printf("Hello World\n");
return (NULL);
}
Mutex lock: 특정 코드 영역의 스레드를 실행할 때 한 번에 하나의 스레드만 실행 가능하도록 하는 방법. <pthread.h>를 include한다.
뮤텍스 객체 초기화
int pthread_mutex_init(pthread_mutex_t *mutex, const pthred_mutexattr_t *attr);
뮤텍스 객체 잠그기
int pthread_mutex_lock(pthread_mutex_t *mutex);
뮤텍스 객체 잠금 해제
int pthread_mutex_unlock(pthread_mutex_t *mutex)
뮤텍스 객체 파괴
int pthread_mutex_destroy(pthread_mutex_t *mutex);
인자 thread를 터널에서 분리시키기. 분리된 스레드는 수행을 종료하고, 할당된 자원을 회수한다.
int pthread_detach(pthread_t thread);
동시에 리소스에 접근 허용이 가능한 개수를 의미하는 정수형 변수. (동시에 사용 가능한 포크 개수)
sem_t *sem_open(const char *name, int oflag, ...);
name이라는 세마포어 객체를 oflag에 따라 생성 혹은 접근.
int sem_close(sem_t *sem);
sem이 가리키는 세마포어를 사용하여 종료
int sem_wait( sem_t *sem);
sem이 가리키는 세마포어를 잠금
int sem_post( sem_t *sem);
sem이 가리키는 세마포어를 잠금 해제
int sem_unlink( const char *name);
name이라는 세마포어 객체를 제거
프로그램 1에서는 철학자들 사이에 포크가 하나씩 있는 구조.
프로그램 2에서는 포크들이 테이블 중앙에 모여 있는 구조.
한 철학자가 식사를 시작한 시점으로부터 time_to_eat 만큼의 시간이 지나면, 바로 잠에 든다.
./philo_one 3 410 200 200
3명의 철학자, 3개의 포크.
200 밀리세컨만큼 먹고, 200 밀리세컨만큼 자고.
410 밀리세컨 내에 못 먹으면 철학자는 죽음.
number_of_philosophers : 철학자의 수, 즉 포크의 갯수
time_to_die : 밀리세컨 단위. 한 철학자가 식사를 시작하지 않으면, 그가 마지막 식사를 시작하거나 시뮬레이션이 시작된지 ‘time_to_die’ 초 내에 그는 죽는다.
time_to_eat : 밀리세컨 단위. 철학자가 식사를 하는 시간. 이 시간동안 철학자는 포크 두 개를 들고 있다.
time_to_sleep: 밀리세컨 단위. 철학자가 자는 시간.
Threads와 mutex를 사용하는 철학자
각각의 철학자 사이에 하나의 포크가 있어서, 결국 모든 철학자들의 양쪽에 포크가 놓여 있게 된다.
철학자들이 포크를 중복 사용하는 것을 막기 위해, 각각의 포크의 상태를 mutex로 보호해야 한다.
각각의 철학자는 thread여야 한다.
Threads와 semaphore을 사용하는 철학자
모든 포크들이 테이블 한가운데에 있다.
메모리 안에 상태는 없지만, 사용 가능한 포크의 개수가 semaphore을 통해 표시된다.
각각의 철학자는 thread여야 한다.
processes와 semaphore을 사용하는 철학자
모든 포크들이 테이블 한가운데에 있다.
메모리 안에 상태는 없지만, 사용 가능한 포크의 개수가 semaphore을 통해 표시된다.
각각의 철학자들은 process여야 하고, 메인 프로세스는 철학자가 아니여야 한다.