12. thread


이번 글은 마지막인 thread에 대해서 정리해보도록 하겠습니다.


프로그래밍의 꽃이라 부를 수 있는 thread ( 쓰 뤠 두으우엑 우엑...공부할 때 마다 극혐 토나온닷..)



여기서 정리하는 thread는 C++ 표준 thread 라이브 러리 입니다. (std::thread)


#include <thread> 헤더가 필요하며


각 OS API의 쓰레드보다 사용하기가 쉽다는 장점이 있습니다.



std::thread의 사용 법은 아래와 같이 간단합니다.


std::thread myThread(
[](){
for(int i = 0; i< 5; i++)
{
std::cout << "Hello~ I am myThread" << std::endl;
}
});
view rawthread.cpp hosted with ❤ by GitHub


std::thread 타입으로 thread를 선언하고 ( ) 안에 함수 내용을 적으시면 됩니다.

위와 같이 람다로 구현하는 방법도 가능합니다.



thread를 생성하고 특정한 시기에 동작하게 하려면 다음과 같이 수행하면 됩니다.


std::thread myThread;
myThread = std::thread(
[]()
{
for(int i = 0; i < 5; i++)
{
std::cout << "Hello World" << std::endl;
}
});
view rawthread.cpp hosted with ❤ by GitHub


위 코드와 같이 myThread를 선언만 해놓고

정의는 추후에 하는 방식으로 내가 원하는 타이밍에 동작하게 할 수 있습니다.


다음, thread의 파라미터 값을 넣는 것도 아래와 같이 수행하면 넣을 수 있습니다.


std::thread myThread = std::thread(
[](int nParam)
{
for(int i = 0; i < 10; i++)
{
std::cout << "thread called : " << nParam << std::endl;
}
}, 4);
view rawthread.cpp hosted with ❤ by GitHub


위 코드의 마지막 줄에 람다 함수가 끝나고 " , 4" 를 넣어준것 과 같이 파라미터를 전달 하면 됩니다~



이번에는 클래스의 멤버 함수를 스레드에서 사용하는 방법입니다.


아마 이 방법이 제일 궁금하셨을텐데요.


위에 적어둔 방법들과 똑같이 thread의 매개변수로 펑션만 던져주시면 됩니다.


class ThreadPara
{
public:
void func()
{
for(int i = 0; i < 5; i++)
std::cout << "ThreadPara Num : " << i << std::endl;
}
};
ThreadPara thread_para;
std::thread myThread(&ThreadPara::func, &thread_para);
view rawthread.cpp hosted with ❤ by GitHub



쓰레드 대기


thread 클래스의 join 함수를 사용하여 스레드가 종료 할 때 까지 대기하는 방법입니다.


 - join() 함수를 호출하면 blocking이 된다.

 - join() 함수를 호출할 수 있는 지 알기 위해서는 joinable() 함수를 사용한다.


std::thread myThread(
[]()
{
for(int i = 0; i < 5; i++)
{
std::cout << "Hello Thread" << std::endl;
}
});
if(myThread.joinable() == true)
myThread.join();
view rawthread.cpp hosted with ❤ by GitHub


쓰레드 식별자


쓰레드를 식별 하는 방법은 get_id() 함수를 사용하면 해당 쓰레드의 식별자를 얻을 수 있습니다.


get_id() 함수를 통해서 멀티쓰레드에서 각각의 쓰레드를 구분 할 수 있지요.


get_id() 함수를 사용하면 멀티스레드에서 공용 리소스에 접근하는 스레드를 알 수 있고,

특정 스레드만 접근할 수 있게 하는게 가능합니다.


std::thread myThread;
myThread.get_id();
std::this_thread::get_id();
view rawthread.cpp hosted with ❤ by GitHub


thread 오브젝트와 (커널)스레드 분리

  • detach 함수를 사용하면 thread 오브젝트와 스레드 연결 고리를 떼어낸다.
  • detach 이후에는 thread 오브젝트는 제어 할 수 없다.
  • detach 와 스레드의 종료는 상관 없다.



std::thread myThread(
[]()
{
for(int i = 0; i < 5; i++)
std::cout << "Hello Thread" << std::endl;
});
myThread.detach();
//myThread.join() Error!! Can't not join!!
view rawthread.cpp hosted with ❤ by GitHub

thread를 한번 detach 한 순간 부터는 그 쓰레드는 완전 독립이 되기 때문에 join과 같은 함수를 사용 할 수가 없습니다.


따라서 그 쓰레드가 언제 어떻게 될진 그 쓰레드한테 달려있다고 볼 수 있지요.


저는 개인적으로 이런식으로 detach를 쓸일이 있나? 하는 생각도 듭니다만...


= _=뭐 언젠가 필요한 때도 있겠지요.



일시중지와 양보

  • sleep_for 와 sleep_until을 사용하면 스레드를 일시 중지 시킬 수 있다.
  • sleep_for 는 지정한 시간 동안 ( 예: 100 밀리 세컨드 동안만 정지)
  • sleep_until 은 지정 시간까지 ( 예: 16시 10분까지 정지)
  • yield를 사용하여 자신(스레드)의 활동을 포기하고 다른 스레드에게 양보한다.
    std::this_thread::yield();


thread 종료
  • 스레드가 실행 중에 프로그램이 종료되면 crash가 발생 할 수 있다.
  • 프로그램 종료 전에 꼭 스레드를 먼저 종료 시키고 프로그램을 종료하도록 한다.



void threadFunction()
{
while(g_IsRunThread)
{
...
}
}
int main()
{
g_IsRunThread = true;
...
g_IsRunThread = false;
myThread.join();
}
view rawthread.cpp hosted with ❤ by GitHub

여기 까지가 기본적인 std::thread에 대한 정리였습니다.


그리고 더 이제 심화적이고 중요한 thread의 공유자원 사용하는 방법과 mutex / lock 에 대해서 다음 글을 통해 살펴보도록 하겠습니다.



출처: https://redforce01.tistory.com/85?category=695802 [[은고] 게임 프로그래밍]

'Thread' 카테고리의 다른 글

Mutex example01  (0) 2019.01.27
[ C++ ] mutex 개념 및 예제  (0) 2019.01.26
[ C++ ] thread 개념 및 예제  (0) 2019.01.26
[12편-2] Modern C++ 정리: thread  (0) 2019.01.26

+ Recent posts