치춘짱베리굿나이스

[Rank 3] Philosophers - Joined & Detached 스레드 예제 본문

42/42s Cursus

[Rank 3] Philosophers - Joined & Detached 스레드 예제

치춘 2021. 9. 4. 11:44

스레드 함수 예제와 다르게 이번에는 메인 스레드와 별개의 스레드에서 하위 스레드를 생성하여 두 속성의 차이를 확인해보았다


pthread_join

/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   test_thread_join.c                                 :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: jiychoi <jiychoi@student.42seoul.kr>       +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2021/08/06 10:25:21 by jiychoi           #+#    #+#             */
/*   Updated: 2021/08/06 11:05:40 by jiychoi          ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

#include	<pthread.h>
#include	<unistd.h>
#include	<stdio.h>
#include	<stdlib.h>

typedef struct s_thread_struct
{
	pthread_t	thread_id;
	int			index;
	int			value;
}				t_thread_struct;

void	*thread_func_2(void *data)
{
	int				index;
	t_thread_struct	*thread;

	index = -1;
	thread = (t_thread_struct *)data;
	while (++index < 10)
	{
		printf("%dth Thread %llu\t:\tindex %d\n",
			thread->index, (unsigned long long)thread->thread_id, index);
		sleep(1);
	}
	return (0);
}

void	*thread_func_1(void *data)
{
	int				index;
	int				thread_err;
	t_thread_struct	*thread_data;

	index = -1;
	thread_data = (t_thread_struct *)data;
	while (++index < 10)
	{
		thread_data[index].index = index;
		thread_err = pthread_create(&thread_data[index].thread_id, NULL,
				thread_func_2, (void *)&thread_data[index]);
		if (thread_err < 0)
			exit(0);
		printf("Sub thread %d created.\n", index);
	}
	index = -1;
	while (++index < 10)
	{
		pthread_join(thread_data[index].thread_id,
			(void **)&(thread_data[index].value));
		printf("Thread index %d Joined.\n", index);
	}
	printf("Parent thread died. byebye...\n");
	return (0);
}

int	main(void)
{
	t_thread_struct	threads[10];
	pthread_t		thread_id;
	int				thread_err;

	printf("this is main thread\n");
	thread_id = 0;
	thread_err = pthread_create(&thread_id, NULL,
			thread_func_1, (void *)threads);
	if (thread_err < 0)
		exit(0);
	printf("Parent thread created.\n");
	pthread_join(thread_id, NULL);
	printf("All the threads call finished\n");
	exit(0);
}

1. 메인 스레드 생성

this is main thread 출력

 

2. 인 스레드 안에서 스레드 생성 (이하 '상위 스레드')

Parent thread created 출력

 

3. 위 스레드 join

상위 스레드 ↔ 메인 스레드간 의존성이 남아있기 때문에, 메인 스레드는 무한루프를 걸어주지 않더라도 상위 스레드가 모든 작업을 마칠 때까지 대기하므로 혼자 종료되지 않는다

 

4. 상위 스레드 안에서 스레드 10개 생성 (이하 '하위 스레드')

Sub thread # created 출력

 

5. 위 스레드 안에서 0번째 하위 스레드 joined 실행

이때 상위 스레드와 0번째 스레드 간 의존성이 있기 때문에, 여기서부터 상위 스레드는 0번째 하위 스레드가 모든 작업을 마칠 때까지 대기한다

 

6. 위 스레드는 마저 동작

각 스레드별로 10번씩 printf + sleep을 반복한다

7. 0번 스레드가 종료되면 0번 스레드의 자원이 회수되면서 (아까 호출했던 joined 함수 때문) 

Thread index 0 Joined 메시지가 출력되고, 1번 스레드에 대해서 join 함수를 호출한다

1번 스레드는 종료되었으므로 1번 스레드의 자원이 회수되면서 Thread index 1 Joined 메시지가 출력되고, 2번 스레드에 대해서 join 함수를 호출한다... 이하 9번 스레드까지 반복

 

8. 모든 하위 스레드의 자원이 회수되고 Joined 메시지가 10번 출력되면 상위 스레드 종료

Parent thread died. byebye...출력 이후 스레드가 리턴문을 만나기 때문에 그대로 상위 스레드는 종료된다

 

9. 상위 스레드 종료 후 메인 스레드 종료

상위 스레드와 메인 스레드간의 의존성 (joined) 때문에 메인 스레드는 죽지 않고 살아있다가, 상위 스레드가 종료되면 자원을 회수하고 All the threads call finished 출력 후 메인 스레드 종료 (프로세스 종료)


pthread_detach

/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   test_thread_detach.c                               :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: jiychoi <jiychoi@student.42seoul.kr>       +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2021/08/06 10:25:21 by jiychoi           #+#    #+#             */
/*   Updated: 2021/08/06 10:47:55 by jiychoi          ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

#include	<pthread.h>
#include	<unistd.h>
#include	<stdio.h>
#include	<stdlib.h>

typedef struct s_thread_struct
{
	pthread_t	thread_id;
	int			index;
	int			value;
}				t_thread_struct;

void	*thread_func_2(void *data)
{
	int				index;
	t_thread_struct	*thread;

	index = -1;
	thread = (t_thread_struct *)data;
	while (++index < 10)
	{
		printf("%dth Thread %llu\t:\tindex %d\n",
			thread->index, (unsigned long long)thread->thread_id, index);
		sleep(1);
	}
	return (0);
}

void	*thread_func_1(void *data)
{
	int				index;
	int				thread_err;
	t_thread_struct	*thread_data;

	index = -1;
	thread_data = (t_thread_struct *)data;
	while (++index < 10)
	{
		thread_data[index].index = index;
		thread_err = pthread_create(&thread_data[index].thread_id, NULL,
				thread_func_2, (void *)&thread_data[index]);
		if (thread_err < 0)
			exit(0);
		printf("Sub thread %d created.\n", index);
	}
	index = -1;
	while (++index < 10)
	{
		pthread_detach(thread_data[index].thread_id);
		printf("Thread index %d detached.\n", index);
	}
	printf("Parent thread died. byebye...\n");
	return (0);
}

int	main(void)
{
	t_thread_struct	threads[10];
	pthread_t		thread_id;
	int				thread_err;

	printf("this is main thread\n");
	thread_id = 0;
	thread_err = pthread_create(&thread_id, NULL,
			thread_func_1, (void *)threads);
	if (thread_err < 0)
		exit(0);
	printf("Parent thread created.\n");
	pthread_detach(thread_id);
	printf("All the threads call finished\n");
	while (1)
		;
}

1. 메인 스레드 생성
this is main thread 출력


2. 메인 스레드 안에서 스레드 생성 (이하 '상위 스레드')
Parent thread created 출력


3. 상위 스레드 detach 후 All the threads call finished 출력
상위 스레드가 detach된 후, 상위 스레드와 메인 스레드의 의존 관계가 깨지기 때문에 메인 스레드의 하위 라인이 그대로 호출되는 것

 

4. 메인문 무한루프 시작
메인 스레드의 종료는 곧 프로세스의 종료이기 때문에, 이를 방지하기 위해 무한루프

 

5. 상위 스레드 안에서 스레드 10개 생성 (이하 '하위 스레드')
Sub thread # created 출력


6. 상위 스레드 안에서 하위 스레드 10개 바로 detach
join이 아니기 때문에 하위 스레드의 동작을 기다리지 않고 상위 스레드도 함께 동작함
각 스레드가 detached 될 때마다 Thread index # detached 출력


7. 상위 스레드 종료
Parent thread died. byebye... 출력 이후 스레드가 리턴문을 만나기 때문에 그대로 상위 스레드는 종료된다


8. 하위 스레드는 마저 동작

각 스레드별로 10번씩 printf + sleep을 반복한다
모든 동작이 끝나면 하위 스레드도 모두 종료되고, 무한루프를 돌고 있는 메인 스레드만 남아있다

이처럼 스레드를 create한 상위 스레드가 메인 스레드가 아닐 경우엔 상위 ↔ 하위 스레드 간 의존성이 완벽하게 사라져 상위 스레드가 죽어도 하위 스레드는 그대로 동작하는 것을 볼 수 있다

Comments