참고: https://www.tutorialspoint.com/cplusplus/cpp_multithreading.htm
멀티쓰레딩은 멀티태스킹에 특화된 형태이며 멀티태스킹은 컴퓨터에서 두 개 이상의 프로그램을 동시에 실행하는 기능을 말합니다. 일반적으로 프로세스 기반과 쓰레드 기반의 두 가지 멀티태스킹 유형이 있습니다.
프로세스 기반 멀티태스킹은 여러 프로그램의 동시 실행을 처리합니다. 쓰레드 기반 멀티태스킹은 동일한 프로그램 내 여러 조각의 동시 실행을 처리합니다.
멀티쓰레드 프로그램에는 동시에 실행할 수 있는 두 개 이상의 부분을 가지고 있습니다. 이러한 프로그램의 각 부분을 쓰레드라고 하며 각 쓰레드는 별도의 실행 경로를 가집니다.
C++ 11 이전에는 멀티쓰레드 응용프로그램에 대한 기본 지원이 없었습니다. 대신 이 기능을 운영체제에 전적으로 의존했습니다.
이 포스트에서는 리눅스 운영체제에서 POSIX를 사용하여 멀티쓰레드 C++ 프로그램을 작성하겠습니다. POSIX thread 또는 pthread는 FreeBSD, NetBSD, GNU/Linux, macOS, Solaris와 같은 많은 Unix 계열 POSIX 시스템에서 사용할 수 있는 API를 제공합니다.
쓰레드 생성
다음은 POSIX thread를 생성하는 구문입니다:
#include <pthread.h>
pthread_create(thread, attr, start_routine, arg);
여기서 pthread_create()는 새로운 쓰레드를 생성하고 실행할 수 있게 만듭니다. 이 루틴은 코드 내 어디서나 여러 번 호출할 수 있습니다. 매개변수에 대한 설명은 다음과 같습니다:
- thread: 서브루틴에서 리턴한 새 쓰레드의 고유 식별자입니다.
- attr: 쓰레드 속성을 설정하는 속성 객체입니다. 쓰레드 속성 객체를 전달하거나 기본 값인 NULL을 전달할 수 있습니다.
- start_routine: 쓰레드가 생성되면 쓰레드가 실행할 C++ 루틴입니다.
- arg: start_routine에 전달할 인수입니다. void 형식의 포인터 참조로 전달해야합니다. 전달할 인수가 없으면 NULL을 사용할 수 있습니다.
프로세스에 의해 생성할 수 있는 최대 쓰레드 수는 구현에 따라 다릅니다. 생성된 쓰레드들은 동등한 레벨을 가지며 또 다른 쓰레드를 생성할 수도 있습니다. 쓰레드 간에는 암묵적인 계층 구조나 종속성이 없습니다.
쓰레드 종료
다음은 POSIX thread의 종료 구문입니다:
#include <pthread.h>
pthread_exit(status);
여기서 pthread_exit()는 스레드를 명시적으로 종료합니다. 일반적으로 pthread_exit() 루틴은 쓰레드가 작업을 완료하고 더 이상 존재할 필요가 없는 경우 호출합니다.
한 쓰레드가 main()이 생성한 쓰레드 보다 먼저 완료되고 pthread_exit()로 종료되더라도 다른 쓰레드는 계속 실행됩니다. 종료되지 않고 계속 실행 중인 쓰레드들은 main()이 완료되면 자동으로 종료됩니다.
기본 예제
다음의 간단한 예제 코드는 pthread_create() 루틴으로 5 개의 쓰레드를 생성합니다. 각 쓰레드는 "Hello World!"를 출력하고 pthread_exit()를 호출하여 쓰레드를 종료합니다.
#include <iostream>
#include <cstdlib>
#include <pthread.h>
using namespace std;
#define NUM_THREADS 5
void * printHello(void *threadid) {
long tid = (long)threadid;
cout << "Hello World! Thread ID: " << tid << endl;
pthread_exit(NULL);
}
int main () {
pthread_t threads[NUM_THREADS];
int rc;
int i;
for (i = 0; i < NUM_THREADS; i++) {
cout << "main() : creating thread, " << i << endl;
rc = pthread_create(&threads[i], NULL, printHello, (void *)i);
if (rc) {
cout << "Error: unable to create thread: " << rc << endl;
exit(-1);
}
}
pthread_exit(NULL);
}
쓰레드에 인수 전달
이 예제는 구조체를 통해 여러 인수를 전달하는 방법을 보여줍니다. 예제에서 보는 것 처럼 arg는 void 형 포인터이기 때문에 쓰레드 콜백에 모든 데이터 유형을 전달할 수 있습니다.
#include <iostream>
#include <cstdlib>
#include <pthread.h>
using namespace std;
#define NUM_THREADS 5
struct thread_data {
int thread_id;
const char * message;
};
void * printHello(void * threadarg) {
struct thread_data * my_data = (struct thread_data *) threadarg;
cout << "Thread ID : " << my_data->thread_id;
cout << " Message : " << my_data->message << endl;
pthread_exit(NULL);
}
int main () {
pthread_t threads[NUM_THREADS];
struct thread_data td[NUM_THREADS];
int rc;
int i;
for (i = 0; i < NUM_THREADS; i++) {
cout << "main() : creating thread, " << i << endl;
td[i].thread_id = i;
td[i].message = "This is message";
rc = pthread_create(&threads[i], NULL, printHello, (void *)&td[i]);
if (rc) {
cout << "Error:unable to create thread," << rc << endl;
exit(-1);
}
}
pthread_exit(NULL);
}
쓰레드 기다리기
다음 두 개의 루틴은 쓰레드를 기다리거나 독립적으로 자원을 할당 합니다:
pthread_join(threadid, status);
pthread_detach(threadid);
pthread_join() 서브루틴은 지정된 "threadid" 쓰레드가 종료될 때 까지 호출 쓰레드를 정지 시킵니다. 쓰레드를 생성할 때 속성에 따라 기다리게할 수 있는 쓰레드 인지 독립적인 자원을 가질 수 있는 쓰레드인지를 정의합니다. joinable 속성으로 생성된 쓰레드만 기다릴 수 있습니다. 쓰레드가 detached 상태로 생성되면 절대 기다릴 수 없습니다.
다음의 예제는 pthread_join() 루틴을 사용하여 쓰레드 완료를 기다리는 방법을 보입니다:
#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>
using namespace std;
#define NUM_THREADS 5
void * wait(void * t) {
long tid = (long)t;
sleep(1);
cout << "Sleeping in thread " << endl;
cout << "Thread with id : " << tid << " ...exiting " << endl;
pthread_exit(NULL);
}
int main () {
int rc;
int i;
pthread_t threads[NUM_THREADS];
pthread_attr_t attr;
void * status;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for (i = 0; i < NUM_THREADS; i++) {
cout << "main() : creating thread, " << i << endl;
rc = pthread_create(&threads[i], &attr, wait, (void *)i);
if (rc) {
cout << "Error:unable to create thread," << rc << endl;
exit(-1);
}
}
pthread_attr_destroy(&attr);
for (i = 0; i < NUM_THREADS; i++) {
rc = pthread_join(threads[i], &status);
if (rc) {
cout << "Error:unable to join," << rc << endl;
exit(-1);
}
cout << "Main: completed thread id :" << i ;
cout << " exiting with status :" << status << endl;
}
cout << "Main: program exiting." << endl;
pthread_exit(NULL);
}
'dev > c++' 카테고리의 다른 글
[c++] 프로세스 생성 (fork) (8) | 2023.06.01 |
---|---|
[c++] 프로세스 ID 가져오기 (getpid, getppid) (7) | 2023.06.01 |
[c++] 더하기, 두 수의 합을 출력 (1) | 2018.04.24 |
[c++] 문자열 여러 행 출력하기 (cout) (0) | 2018.04.24 |
댓글