unique_lock는 쉽게 말하면 lock_guard에 기능이 더해진 것이라고 볼 수 있습니다.

lock_guard의 경우 정의와 동시에 락을 걸고, 파괴될 때만 락을 풀 수 있습니다.

 

그에 비해 unique_lock은 정의와 동시에 락을 걸 수도 있고, 또는 뒤에 락을 걸 수도 있습니다. 또 락을 푸는 것도 원하는 대로 조절이 가능하며 try_lock이나 try_lock_for, try_lock_until 등도 지원합니다. 그리고 unique_lock끼리 소유한 뮤텍스 객체를 서로 교환도 할 수 있으며, 뮤텍스 객체를 얻거나 해제할 수도 있습니다.

 

간단한 경우에는 lock_guard가 사용하기 편하지만 뮤텍스를 다양하게 사용하고 싶은 경우에는 unique_lock이 훨씬 더 좋습니다.

 

 

unique_lock 생성

unique_lock 클래스의 생성자는 다양한 방법으로 뮤텍스를 사용할 수 있도록 여러 버전이 준비 되어 있습니다.

 

unique_lock() noexcept;

unique_lock(unique_lock&& Other) noexcept;

explicit unique_lock(mutex_type& Mtx);

unique_lock(mutex_type& Mtx, adopt_lock_t Adopt);

unique_lock(mutex_type& Mtx, defer_lock_t Defer) noexcept;

unique_lock(mutex_type& Mtx, try_to_lock_t Try);

template<class Rep, class Period>

   unique_lock(mutex_type& Mtx,

      const chrono::duration<Rep, Period> Rel_time);

template<class Clock, class Duration>

   unique_lock(mutex_type& Mtx,

      const chrono::time_point<Clock, Duration> Abs_time);

unique_lock(mutex_type& Mtx,

   const xtime *Abs_time) noexcept;

 

unique_lock의 사용 예는 아래와 같습니다.

 

std::mutex m;

....

// 락을 만들고 동시에 뮤텍스의 소유권을 가진다

std::unique_lock lck(m, std::adopt_lock);

 

 

std::mutex m;

....

// 락을 만들지만 뮤텍스의 소유권은 가지지 않는다

std::unique_lock lck(m,std::defer_lock);      

...

if (lck.try_lock()) {

....

}                   

 

 

std::unique_lock<std::timed_mutex>

        lk(m,std::chrono::milliseconds(3));

....

if(lk) {

    process(data);

}                   

 

 

 

unique_lock 멤버 함수

 

- void lock();

- mutex_type *mutex() const _NOEXCEPT;

- explicit operator bool() _NOEXCEPT

- unique_lock& operator=(

    unique_lock&& Other

  ) _NOEXCEPT;

- bool owns_lock() const _NOEXCEPT;

- mutex_type *release() _NOEXCEPT;

- void swap(

    unique_lock& Other

  ) _NOEXCEPT;

- bool try_lock() _NOEXCEPT;

- template<class Rep,

    class Period>

  bool try_lock_for(

     const chrono::duration<Rep,

     Period>& Rel_time

  );

- template<class Clock, class Duration>

    bool try_lock_until(const chrono::time_point<Clock, Duration>& Abs_time);

    bool try_lock_until(const xtime *Abs_time);

- void unlock();

 

저작자 표시
신고
by 흥배 2013.07.15 08:00

std::mutex try_lock을 사용하면 뮤텍스의 소유권을 가질 수 있으면 true를 반환하고, 그렇지 못하면 바로 false를 반환하므로 소유권을 얻고 싶으면 또 다시 try_lock을 호출해야 합니다. 그런데 공유자원을 사용하는 시간이 아주 짧은 경우도 있다면 특정 시간까지만 계속 락을 시도하여 뮤텍스의 소유권을 가지기를 바라는 경우가 있습니다. 이럴 때 사용하는 것이 timed_mutex입니다.

 

timed_mutex std::mutex의 모든 기능을 다 가지고 있으면서 try_lock_for try_lock_until 함수 두 개가 더 있습니다. 이 함수들은 시간을 사용하여 뮤텍스 소유를 시도합니다. 시간은 std::chrono로 설정합니다.

 

try_lock_for는 지정한 시간 동안 락을 걸어봅니다.

template<class Rep, class Period>

   bool try_lock_for(const chrono::duration<Rep, Period>& Rel_time);

 

// 10초 동안 mutex의 소유권을 얻을 때까지 시도

if( mutex.try_lock_for(std::chrono::seconds(10)) )

{

           // 공유 자원 사용

           mutex.unlock();

}

 

 

try_lock_until은 지정한 시간까지 뮤텍스의 소유를 시도합니다.

 

template<class Clock, class Duration>

   bool try_lock_for(const chrono::time_point<Clock, Duration>& Abs_time);

bool try_lock_until(const xtime *Abs_time);

 

std::chrono::system_clock::time_point CurTime = std::chrono::system_clock::now();

std::chrono::seconds dura_sec( 5 );

 

// 현재 시간에서 5초 후까지만 mutex를 소유하려고 시도한다

if( mutex.try_lock_until(CurTime + dura_sec) )

{

           // 공유 자원 사용

           mutex.unlock();

}


 

 

recursive_timed_mutex

recursive_timed_mutex std::mutex에 시간 기능이 추가된 timed_mutex 처럼 recursive_mutex에 시간 기능이 추가된 것입니다.

recursive_mutex에 추가된 함수나 사용 방법은 timed_mutex와 비슷합니다.

 

 

저작자 표시
신고
by 흥배 2013.07.08 08:00

std::mutex lock 멤버 함수의 설명을 보면 lock을 호출한 함수에서 unlock을 호출하지 않은 상태에서 또 다시 lock을 호출하면 알 수 없는 동작을 한다고 되어 있습니다.

 

스레드에서 lock을 호출한 후 다시 lock을 호출하는 경우는 아래와 같은 경우입니다.

 

class buffer {

    list<int> queue;

    std::mutex mut;

public:

    bool empty() {

        std::lock_guard<std::mutex> lock(mut);

        return queue.empty();

    }

    ...

    int pop() throw(out_of_range) {

        std::lock_guard <std::mutex> lock(mut);

        while (empty())

        {   

……..

        }

        int tmp = queue.front();

        queue.pop_front();

        return tmp;

     }

};

코드 출처 : http://d.hatena.ne.jp/hidemon/20081218/1229555003

 


위의 buffer 클래스를 보면 pop() 함수를 호출하면 먼저 mutex로 락을 건 다음 empty() 함수를 호출하는데 empty도 같은 mutex를 사용하여 lock을 걸고 있습니다. 즉 이미 락을 건 mutex에 또 lock을 걸고 있습니다. 이런 경우 데드락 상황에 빠질 수가 있습니다. 이 문제를 풀기 위해서는 recursive_mutex를 사용합니다.

recursive_mutex는 같은 스레드에서 lock을 건 후 또 다시 lock을 걸어도 괜찮습니다. lock을 건 횟수만큼 꼭 unlock을 호출해야 합니다.

 

그럼 아래는 위의 buffer 클래스를 recursive_mutex를 사용하여 올바르게 수정한 것 입니다. 단순하게 std::mutex std::recursive_mutex로 바꾸면 됩니다.

(std::mutex std::recursive_mutex의 사용 방법은 같습니다)

 

class buffer {

    list<int> queue;

    std::recursive_mutex mut;

public:

    bool empty() {

        std::lock_guard<std::recursive_mutex> lock(mut);

        return queue.empty();

    }

    ...

    int pop() throw(out_of_range) {

        std::lock_guard <std::recursive_mutex> lock(mut);

        while (empty())

        {   

……..

        }

        int tmp = queue.front();

        queue.pop_front();

        return tmp;

     }

};

 

 

저작자 표시
신고
by 흥배 2013.07.01 08:00

std::mutex를 사용하여 복수의 스레드에서 사용하는 공유 자원을 서로 침범 없이 사용할 수 있습니다. 그러나 lock 사용하여 뮤텍스에 대한 소유권을 얻은 후 실수로 unlock을 하지 않으면 아무도 그 공유 자원을 사용하지 못하는 데드락 상태에 빠질 수 있습니다.

 

예를 들면 아래와 같은 경우가 이런 실수를 하기 쉽습니다.

..........

mutex.lock();

 

if( n < 10 ) {

return false;

}

.......

mutex.unlock();

 

위 코드에서 n 10보다 작은 경우 unlock을 하지 않고 바로 빠져 나오게 됩니다. 이거 이외에도 lock을 사용한 후 예외가 발생하여 throw 되는 경우 unlock을 하지 않는 실수를 할 수 있습니다.

 

이런 실수를 방지하기 위해서 lock_guard 라는 유틸리티 클래스가 있습니다.

mutex lock_guard와 같이 사용하면 lock_guard 클래스가 인스턴스화 될 때 자동으로 lock을 호출하고, 인스턴스가 파괴될 때 자동으로 unlock을 호출합니다.

 

template<class Mutex>

class lock_guard;

 

다음은 lock_guard를 사용한 예입니다.

 

< 예제. 2 >

#include <thread>

#include <iostream>

#include <mutex>

 

int main()

{

           std::mutex mtx_lock;

 

           std::thread Threads1( [&] ()

              {

                        for( int i = 0; i < 5; ++i )

                        {

                                          std::lock_guard<std::mutex> guard(mtx_lock);

                                          std::cout << "Thread Num : " << i << std::endl;

                        }

              } );

 

 

           std::thread Threads2;

           Threads2 = std::thread( [&] ()

              {

                        for( int i = 10; i < 15; ++i )

                        {

                                          std::lock_guard<std::mutex> guard(mtx_lock);

                                          std::cout << "Thread Num : " << i << std::endl;

                        }

              } );

 

           std::thread Threads3 = std::thread( [&] ( int nParam )

              {

                      for( int i = 20; i < 25; ++i )

                      {

                                 std::lock_guard<std::mutex> guard(mtx_lock);

                                 std::cout << "Thread Parameter : " << nParam << std::endl;

                      }

              }, 4 );

 

          

 

           Threads1.join();

           Threads2.join();

           Threads3.join();

          

           return 0;

}

 

lock_guard는 뮤텍스의 소유와 해제에 대한 RAII(리소스 확보 및 초기화) 패턴이라고 볼 수 있습니다.

저작자 표시
신고
by 흥배 2013.06.24 08:00

병렬 프로그래밍을 해보면 싫든 좋든 여러 스레드에서 하나의 객체에 동시에 접근하는 경우가 발생합니다. 앞선 std::thread에 관한 글을 보면 소개한 예제 중 그런 경우를 보실 수 있을 겁니다.

 

< 예제 >

#include <thread>

#include <iostream>

 

int main()

{

           std::thread Threads1( [] ()

              {

                        for( int i = 0; i < 5; ++i )

                        {

                                          std::cout << "Thread Num : " << i << std::endl;

                        }

              } );

 

 

           std::thread Threads2;

           Threads2 = std::thread( [] ()

              {

                        for( int i = 10; i < 15; ++i )

                        {

                                          std::cout << "Thread Num : " << i << std::endl;

                        }

              } );

 

           std::thread Threads3 = std::thread( [] ( int nParam )

              {

                      for( int i = 20; i < 25; ++i )

                      {

                                std::cout << "Thread Parameter : " << nParam << std::endl;

                      }

              }, 4 );

 

           getchar();

           return 0;

}

 

위 예제에서 ‘std::cout’ 각 스레드에 동시에 접근하고 있습니다. 그래서 실행하면 아래와 같은 결
과가 나옵니다.


실행 화면을 보면 출력 결과 중 일부가 뒤죽박죽 되어 있는 것을 알 수 있습니다. 이유는 Thread1 스레드에서 출력스트림 결과를 다 출력하기 전에 Threads2가 출력스트림을 사용하여 발생한 문제입니다. 이런 것을 data-race(데이터 경합) 이라고 합니다.

 

그런데 위 예제를 여러 번 실행해 보면 아래처럼 올바르게 나올 때도 있습니다.



사실 이런 부분이 병렬 프로그래밍의 어려움 중의 하나입니다. 여러 스레드에서 하나의 공유 자원을 사용할 때 타이밍에 의해서 순서대로 사용할 수도 있고 그렇지 못할 수도 있기 때문에 버그 발생이 언제 어떻게 생길지 알기 힘듭니다.

 

병렬 프로그래밍을 할 때는 언제나 공유 자원을 최소한으로 하고, 공유 자원은 꼭 동기화 객체를 사용하여 여러 스레드가 동시에 사용하지 못하도록 해야 합니다.

 

위의 문제는 동기화 객체를 사용하면 해결 할 수 있습니다. 여기서는 앞선 글에서 사용한 적이 있는 뮤텍스(std::mutex)를 사용하겠습니다.

 

그럼 위 예제를 mutex를 사용하여 문제를 해결해 보겠습니다.

 

<예제 1 >

#include <thread>

#include <iostream>

#include <mutex>

 

int main()

{

           std::mutex mtx_lock;

 

           std::thread Threads1( [&] ()

              {

                        for( int i = 0; i < 5; ++i )

                        {

                                          mtx_lock.lock();

                                          std::cout << "Thread Num : " << i << std::endl;

                                          mtx_lock.unlock();

                        }

              } );

 

 

           std::thread Threads2;

           Threads2 = std::thread( [&] ()

              {

                        for( int i = 10; i < 15; ++i )

                        {

                                          mtx_lock.lock();

                                          std::cout << "Thread Num : " << i << std::endl;

                                          mtx_lock.unlock();

                        }

              } );

 

           std::thread Threads3 = std::thread( [&] ( int nParam )

              {

                      for( int i = 20; i < 25; ++i )

                      {

                                 mtx_lock.lock();

                                 std::cout << "Thread Parameter : " << nParam << std::endl;

                                 mtx_lock.unlock();

                      }

              }, 4 );

 

          

 

           getchar();

           return 0;

}

 

< 실행 결과>



std::mutex를 사용하기 위해서는 아래의 헤더 파일을 추가합니다.

#include <mutex>

 

스레드에서 공유 자원을 사용할 때는 아래 처럼 락을 걸어서 뮤텍스 mtx_lock의 소유권을 얻어서 다른 스레드가 접근하지 못하도록 합니다. 그리고 공유 자원을 다 사용하였다면 락을 해제하여 mtx_lock의 소유권을 버립니다.

mtx_lock.lock();

std::cout << "Thread Num : " << i << std::endl;

mtx_lock.unlock();

 

락을 건 후(lock) 락을 풀(unlock) 때까지는 다른 스레드는 대기를 하고, 락을 풀면 대기하고 있는 스레드 중 하나가 락을 건 후 공유 자원을 사용합니다.

그러므로 락을 건 후에는 꼭 락을 풀어야 하고(만약 풀지 않으면 데드락 상황에 빠지게 됩니다), 락을 사용하는 부위가 너무 빈번하면(스레드 대기가 늘어나므로) 병렬 프로그래밍의 장점이 많이 약해집니다.

 

 

try_lock

std::mutex lock unlock 이외에 try_lock 이라는 멤버 함수가 있습니다.

bool try_lock();

 

스레드에서 lock을 호출할 때 다른 스레드가 이미 lock을 호출하여 뮤텍스의 소유권을 가진 후 아직 unlock을 호출하지 않았다면 그 자리에서 대기를 합니다. 그러나 try_lock은 대기를 하지 않고 false를 반환합니다(뮤텍스의 소유권을 얻지 못한 경우). 반대로 true를 반환한 경우는 뮤텍스에 대한 소유권을 가지게 되므로 공유자원을 안전하게 사용할 수 있습니다.

 

try_lock을 사용하는 경우는 만약 공유 자원을 다른 스레드에서 사용 중이면 스레드가 대기하면서 그냥 시간을 소비하지 않고 또 다른 작업을 하도록 할 때 사용하면 좋습니다.

 


 

ps : 참고로 std::mutex Windows OS에서는 내부적으로는 크리티컬섹션을 사용합니다.

 

 

저작자 표시
신고
by 흥배 2013.06.03 08:00

앞 선 글 중 ‘std::thread - 2. Join’에서 join을 호출하지 않은 경우 에러 창이 발생하였습니다.


 

이것은 C++11 thread 사양에 의해서 thread 오브젝트가 파괴될 때 join이나 detach를 호출하지 않은 경우 std::terminate를 호출하여 프로그램을 종료하도록 되어 있기 때문입니다.

 

< 예제. 9 >

#include <thread>

#include <iostream>

 

int main()

{

           int nThreadRunCount = 0;

          

           {

                      std::thread Thread = std::thread( [&] ()

                       {

                          for( int i = 0; i < 10; ++i )

                          {

                                ++nThreadRunCount;

                                                               

                                std::cout << "Thread1 ID : " << Thread.get_id() << std::endl;

                          }

                       } );

           }

 

           getchar();

           return 0;

}

 


<예제.9>를 실행하면 에러가 발생하고 아래의 콜스택을 보면



thread 오브젝트의 소멸자에서 terminate를 호출하는 것을 알 수 있습니다.



이것으로 thread에 대해서 기능 위주로 간단하게 살펴 보았습니다. 앞으로 공부해야 할 것들이 더 있어서 남은 것들을 설명 후 다시 thread 사용에 대해서 깊게 들어 가겠습니다.

 

다음부터는 병렬 프로그래밍에서 절대 빠질 수 없는 동기화 객체에 대해서 설명하겠습니다.

 

 

저작자 표시
신고
by 흥배 2013.05.28 08:00

sleep_for sleep_until 함수는 스레드를 일시 중지 시킬 때 사용하는 것입니다.

이 두 함수의 차이는 이름에서 쉽게 알 수 있는데 sleep_for는 특정 시간 동안 일시 중지 시키고 싶을 때(. 6초 동안 중지) 사용하고, sleep_until는 어떤 시간이 될 때까지(. 1410분까지) 중지 시킬 때 사용합니다.

 

sleep_for sleep_until 함수는 thread의 멤버는 아니고 this_thread 네임 스페이스에 속해 있습니다.

 

< 예제. 8 >

#include <iostream>

#include <chrono>

#include <thread>

 

int main()

{

           std::cout << "sleep_for 테스트 시작" << std::endl;

   

           std::chrono::seconds dura( 3 );

   

 

           std::chrono::system_clock::time_point StartTime = std::chrono::system_clock::now();

 

           std::this_thread::sleep_for( dura );

   

           std::chrono::system_clock::time_point EndTime = std::chrono::system_clock::now();

 

           std::chrono::seconds sec = std::chrono::duration_cast<std::chrono::seconds>(EndTime - StartTime);

          

           std::cout << "경과 시간()" << sec.count() << std::endl;

 

 

 

          

           std::cout << "sleep_until 테스트 시작" << std::endl;

 

           StartTime = std::chrono::system_clock::now();

 

           std::chrono::seconds dura_sec( 5 );

           std::this_thread::sleep_until( StartTime + dura_sec );

          

           EndTime = std::chrono::system_clock::now();

 

           sec = std::chrono::duration_cast<std::chrono::seconds>(EndTime - StartTime);

          

           std::cout << "경과 시간()" << sec.count() << std::endl;

}

 

< 실행 결과 > 


 

yield는 스레드가 자신에게 할당 되어 있는 시간을 포기하고 다른 실행 스레드에게 처리를 양도합니다.

std::this_thread::yield();

저작자 표시
신고
by 흥배 2013.05.20 08:00

hardware_concurrency()는 하드웨어 스레드 컨텍스트 수를 알려 주는 함수입니다.

스레드 컨텍스트는 CPU , 코어 수, 하이퍼 스레드와 관계가 있습니다.

 

하드웨어 스레드 컨텍스트 수는 Windows '작업 관리자' '성능' 탭에서 볼 수 있습니다.





제 컴퓨터는 CPU 하나에 코어는 4개이고, 하이퍼 스레딩을 지원하지 않는 CPU라서 CPU 사용 현황에 4개의 그림만 나옵니다. 그래서 저는 hardware_concurrency() 함수를 실행하면 결과는 4가 나옵니다.

 

관례적으로 프로그램에서 멀티 스레드를 만들 때 (하드웨어 스레드 컨텍스트 수 * 2) +1 이라는 공식으로 나온 수 만큼 만들면 좋다고 합니다. 이때 hardware_concurrency() 함수를 사용하면 좋습니다.

그리고 만약 hardware_concurrency()를 사용할 수 없는 경우라면 0 을 반환 합니다.

 

< 예제. 7 >

#include <thread>

#include <iostream>

 

 

int main()

{

           std::cout << "하드웨어 컨텍스트 수 : " << std::thread::hardware_concurrency() << std::endl;

 

           return 0;

}

 

< 실행 결과 >


저작자 표시
신고
by 흥배 2013.05.10 08:00

detach 함수는 thread 오브젝트에 연결된 스레드를 떼어냅니다.

그래서 detach 이후에는 thread 오브젝트로 스레드를 제어할 수 없습니다. 그러나 detach를 호출했다고 해서 관련된 스레드가 종료 되는 것이 아닙니다. thread 오브젝트와 스레드의 연결이 끊어지는 것입니다.

 

 

< 예제. 5 >

#include <thread>

#include <iostream>

 

int main()

{

           int nThreadRunCount = 0;

           std::thread Thread = std::thread( [&] ()

                                {

                                           for( int i = 0; i < 10; ++i )

                                          {

                                          ++nThreadRunCount;

                                         

                                          std::cout << "Thread1 ID : " << Thread.get_id() << std::endl;

                                          }

                              } );

 

           while( nThreadRunCount < 3 )

           {

           }

 

           Thread.detach();

 

           //Thread.join();

 

           getchar();

           return 0;

}

 

< 실행 결과 >


 

<예제. 5>의 결과를 보면 detach 이후 스레드 id가 초기화 됨을 알 수 있습니다. 그리고 위 예제에서 join() 메소드를 주석 처리하고 있는데 만약 주석을 풀면 아래와 같은 에러가 발생합니다.



 

이렇게 thread 오브젝트가 스레드를 가지지 않는데 join 함수를 호출하면 에러가 발생하는 것을 막기 위해서는 joinable 함수를 사용합니다. joinable 함수를 호출하여 반환 값이 true인 경우에만  join 함수를 호출하면 위와 같은 에러를 막을 수 있습니다.

 

< 예제. 6 >

#include <thread>

#include <iostream>

#include <mutex>

 

int main()

{

           std::mutex mtx_lock;

 

           int nThreadRunCount = 0;

           std::thread Thread = std::thread( [&] ()

                                {

                                for( int i = 0; i < 10; ++i )

                                {

                          ++nThreadRunCount;

                                                               

                                  mtx_lock.lock();

                                  std::cout << "Thread1 ID : " << Thread.get_id() << std::endl;

                                  mtx_lock.unlock();

                                }

                          } );

 

           while( nThreadRunCount < 3 )

           {

                     mtx_lock.lock();

                     std::cout << "Thread Is Joinable : " << Thread.joinable() << std::endl;

                     mtx_lock.unlock();

           }

 

           Thread.detach();

 

           std::cout << "Thread Is Joinable : " << Thread.joinable() << std::endl;

 

           getchar();

           return 0;

}

 

< 실행 결과 3>

 

 

저작자 표시
신고
by 흥배 2013.05.03 08:00

앞선 글의 <예제.1>을 보면 제일 아래에

 

#include <thread>

#include <iostream>

 

int main()

{

std::thread Thread1( [] ()

......

 

getchar();

return 0;

}

 

마지막 줄에서 두 번째에 getchar();를 사용했습니다. 만약 이것을 제거하고 예제 코드를 실행하면 다음과 같은 에러가 발생합니다.



이 에러가 발생하는 이유는 아직 스레드는 실행 중인데 프로그램이 종료 되었기 때문입니다. getchar();를 사용하여 유저의 입력을 받을 때까지 대기하도록 하여 문제를 해결할 수 있지만 이것은 임시 방편입니다. 올바른 방법은 thread 클래스의 join 함수를 사용하여 스레드의 실행이 끝날 때까지 대기하도록 합니다.

<예제.1> join을 사용하도록 수정하면 아래와 같습니다.

 

< 예제. 2 >

#include <thread>

#include <iostream>

 

int main()

{

std::thread Thread1( [] ()

           {

              for( int i = 0; i < 5; ++i )

              {

                     std::cout << "Thread Num : " << i << std::endl;

              }

           } );

 

 

           std::thread Thread2;

           Threads = std::thread( [] ()

           {

              for( int i = 10; i < 15; ++i )

              {

                 std::cout << "Thread Num : " << i << std::endl;

              }

           } );

 

           std::thread Thread3 = std::thread( [] ( int nParam )

                     {

                       for( int i = 20; i < 25; ++i )

                       {

                         std::cout << "Thread Parameter : " << nParam << std::endl;

                       }

                      }, 4 );

 

          

 

           Thread1.join();

Thread2.join();

Thread3.join();

          

return 0;

}

 

<예제.2>는 제일 아래에서 각 thread 객체의 join을 호출하고 있어서 Thread1, Thread2, Thread3는 생성과 동시에 실행이 되는데 만약 Thread1의 실행이 끝난 후 Thread2가 실행되고 이것이 끝나면 Thread3를 실행하려면 thread 객체를 생성 후 join을 호출하면 됩니다.

 

< 예제. 3 >

#include <thread>

#include <iostream>

 

int main()

{

std::thread Thread1( [] ()

           {

              for( int i = 0; i < 5; ++i )

              {

                     std::cout << "Thread Num : " << i << std::endl;

              }

           } );

           Thread1.join();

 

 

           std::thread Thread2;

           Threads = std::thread( [] ()

           {

              for( int i = 10; i < 15; ++i )

              {

                 std::cout << "Thread Num : " << i << std::endl;

              }

           } );

           Thread2.join();

 

 

           std::thread Thread3 = std::thread( [] ( int nParam )

                     {

                       for( int i = 20; i < 25; ++i )

                       {

                         std::cout << "Thread Parameter : " << nParam << std::endl;

                       }

                      }, 4 );

Thread3.join();

          

return 0;

}

 

< 결과 >




저작자 표시
신고
by 흥배 2012.11.19 08:30
| 1 2 3 |

티스토리 툴바