C++에서 std::thread의 기본 사용법은?
A1: std::thread는 C++11부터 표준 라이브러리에 추가된 스레딩 라이브러리로, 멀티스레딩 프로그래밍을 쉽게 구현할 수 있도록 도와줍니다. 스레드는 병렬로 실행 가능한 작업 단위입니다.
---
Q2: std::thread를 사용하려면 어떤 헤더를 포함해야 하나요?
A2: ` include
---
Q3: std::thread 객체는 어떻게 생성하나요?
A3: std::thread 객체는 실행할 함수 또는 함수 객체와 그 함수에 전달할 인자를 생성자에 넘겨서 생성합니다.
```cpp
include
void foo(int x) {
// 작업 내용
}
int main() {
std::thread t(foo, 10); // foo(10)을 새 스레드에서 실행
t.join(); // 메인 스레드에서 t 스레드가 종료될 때까지 대기
return 0;
}
```
---
Q4: 스레드를 생성할 때 전달할 수 있는 함수 종류는 무엇인가요?
A4:
- 자유 함수 (free function)
- 람다 함수
- 멤버 함수 (객체와 함께 호출 필요)
- 함수 객체 (functor)
예:
```cpp
include
include
struct Functor {
void operator()(int x) {
std::cout << "Functor: " << x << std::endl;
}
};
class Foo {
public:
void memberFunc(int x) {
std::cout << "Member Func: " << x << std::endl;
}
};
int main() {
std::thread t1([](int x){ std::cout << "Lambda: " << x << std::endl; }, 5);
Functor f;
std::thread t2(f, 10);
Foo foo;
std::thread t3(&Foo::memberFunc, &foo, 15);
t1.join();
t2.join();
t3.join();
}
```
---
Q5: std::thread 객체를 실행한 후 반드시 해야 할 작업은 무엇인가요?
A5:
- 스레드를 종료시켜야 하며, `join()` 혹은 `detach()`를 호출해야 합니다.
- `join()`은 메인 스레드가 해당 스레드가 끝날 때까지 기다리는 것이고,
- `detach()`는 스레드를 분리하여 백그라운드에서 실행하게 합니다.
만약 어떤 것도 호출하지 않고 std::thread 객체가 소멸되면 프로그램이 `std::terminate()`를 호출해 종료됩니다.
---
Q6: std::thread의 기본적인 사용 예시는 어떻게 되나요?
A6:
```cpp
include
void say_hello() {
std::cout << "Hello from thread!" << std::endl;
}
int main() {
std::thread t(say_hello); // say_hello를 별도 스레드에서 실행
t.join(); // 스레드 종료를 기다림
std::cout << "Hello from main!" << std::endl;
return 0;
}
```
---
Q7: 스레드 생성 시 인자 전달은 어떻게 하나요?
A7: 함수 인자를 std::thread 생성자에 추가로 넘기면, 스레드 함수에서 해당 인자를 받습니다. 인자는 복사되거나 이동됩니다.
```cpp
void print_num(int n) {
std::cout << n << std::endl;
}
std::thread t(print_num, 42);
```
참고로 참조 인자를 넘기려면 `std::ref`를 사용해야 합니다. 스레드 내부에서 인자를 복사하지 않고 참조로 받게 됩니다.
```cpp
include
void print_num_ref(int& n) {
std::cout << n << std::endl;
}
int main() {
int x = 100;
std::thread t(print_num_ref, std::ref(x));
t.join();
}
```
---
Q8: std::thread 객체를 복사할 수 있나요?
A8: 아니요. std::thread는 복사 생성자가 삭제되어 복사할 수 없습니다. 다만, 이동 생성자와 이동 대입 연산자는 제공하므로 이동만 가능합니다.
---
Q9: 여러 개의 std::thread를 관리하는 방법은?
A9: std::vector
```cpp
include
include
include
void worker(int id) {
std::cout << "Worker " << id << " start\n";
// 작업 ...
std::cout << "Worker " << id << " end\n";
}
int main() {
std::vector
for (int i = 0; i < 5; ++i) {
threads.emplace_back(worker, i);
}
for (auto& t : threads) {
t.join();
}
}
```
---
Q10: std::thread 사용 시 주의할 점은 무엇인가요?
A10:
- 스레드가 예외를 던질 경우 해당 예외는 별도 스레드 영역에서 발생하므로 주 스레드와 별개로 처리해야 합니다.
- 공유 자원 접근 시 동기화 (mutex 등)를 사용해야 데이터 경합을 방지합니다.
- `join()` 혹은 `detach()`를 반드시 호출해 스레드 객체가 소멸될 때 종료 상태가 아니면 안 됩니다.
- 참조 전달 시 `std::ref`를 사용해야 합니다.
---
요약하면, std::thread는 함수나 함수 객체, 람다 등을 별도의 스레드로 실행시킬 수 있으며, 생성 시 인자를 넘기고, 실행 후 반드시 join() 또는 detach()를 호출하여 스레드 종료 처리를 해주어야 하는 C++ 표준 라이브러리 클래스입니다.
작성자:
김서하 [비회원]
| 작성일자: 1년 전
2024-09-20 17:11:34
조회수: 147 | 댓글: 0 | 좋아요: 0 | 싫어요: 0
조회수: 147 | 댓글: 0 | 좋아요: 0 | 싫어요: 0
내용이 부정확하다면 싫어요를 클릭해주세요.