열렬히.뛰기

개조하기

école 42 > philosopher > philosopher : 진행 상황 > 개조하기

너무 오류가 많아서 시작한 개조하기. 그렇지만 많은 것을 배웠다.

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 배열을 하나 만드는 것이 현명하다.