너무 오류가 많아서 시작한 개조하기. 그렇지만 많은 것을 배웠다.
1. 데이터 레이스
뮤택스로 감싼 공간과 관련된 부분(=변수)는 반드시 공유자원이라고 생각해주자.
해당 공유자원(=변수)을 쓰는 다른 코드도 반드시 뮤택스로 감싸주자.
c
...
pthread_mutex_lock(&tools->eating_mutex);
philo_print(philo, "is eating");
philo->eating_num += 1;
eat_start = get_time();
philo->last_eat = get_time();
pthread_mutex_unlock(&tools->eating_mutex);
...
c
...
pthread_mutex_lock(&tools->eating_mutex);
while (i < tools->total_philo)
{
if (philo[i].eating_num >= tools->total_eat)
flag++;
i++;
}
if (flag == tools->total_philo)
{
pthread_mutex_lock(&tools->died_flag_mutex);
tools->died_flag = 1;
pthread_mutex_unlock(&tools->died_flag_mutex);
pthread_mutex_unlock(&tools->eating_mutex);
return (1);
}
pthread_mutex_unlock(&tools->eating_mutex);
...
2. 포크를 잡다가 죽는 경우
포크를 잡고 나서 죽는 걸 파악하기.
- 뮤택스를 잠근다.
- 해당 배열을 0 → 1로 바꾼다.
- 죽었는지 확인한다. (이게 먼저!)
- printf를 이용해 문자열을 출력한다.
3. 쓰레드 과다 생성 시
이런 경우 쓰레드를 다 만들어지기도 전에 먹기 시작.
마지막에 만들어진 쓰레드는 먹기도 전에 죽게 된다.
이를 방지하기 위해서 뮤택스를 쓰레드 행동 제어용으로 쓸 수 있다.
c
static void *threads_action(void *arg)
{
int i;
t_box *tools;
t_philo *thread;
thread = (t_philo *)arg;
tools = thread->tools;
i = 0;
pthread_mutex_lock(&tools->start_mutex);
pthread_mutex_unlock(&tools->start_mutex);
if (thread->id % 2 == 0)
usleep(arg_usleep(tools));
while (!philo_check(tools))
{
if (thread_eat(thread, tools))
break ;
if (philo_check(tools))
break ;
thread_sleep(thread, tools);
if (philo_check(tools))
break ;
philo_print(thread, "is thinking");
}
return (arg);
}
c
int philo_execute(t_box *tools, t_philo *philo)
{
int i;
void *select;
i = 0;
if (tools->total_philo == 1)
{
tools->init_point = get_time();
return (philo_single(tools, philo));
}
pthread_mutex_lock(&tools->start_mutex);
while (i < tools->total_philo)
{
philo[i].philo_begin = get_time();
philo[i].last_eat = get_time();
select = (void *)&(philo[i]);
if (pthread_create(&(philo[i].thread_id), NULL, threads_action, select))
return (1);
i++;
}
tools->init_point = get_time();
pthread_mutex_unlock(&tools->start_mutex);
philo_monitor(tools, philo);
philo_free(tools);
return (0);
}
4. 자원의 할당
뮤택스 그 자체는 자원이(포크가) 되어서는 안된다.
따라서 포크 역할을 해줄 수 있는 int 배열을 하나 만드는 것이 현명하다.