본문 바로가기

Language/C++

c++ thread, mutex, atomic

C++ Thread

#include <thread> // 선언.

using namesapce std;

void somefunction()
{
    for (int cnt =0; cnt < 1000; ++cnt)
		cout << "thread function" << cnt << endl;
}

int main()
{
    thread Thread(&somefunction, <argv>) //인자는 최대 4개까지 넘길 수 있다 한다.
   	Thread.join(); 
    /*
    스레드 메인함수가 리턴해줄때까지 기다렸다가 종료해준다. 안쓰면 에러난다.
    ex) 만약 스레드 메인함수에서 리턴이 없이 while(true)라면 해당 스레드는 block 상태이기때문에 무한정 기다릴것이다.
    join()을 쓰면 생각보다 느리다.
    
    Thread.detach(); 를 쓰면 join을 안써도된다.
    detach 함수는 thread 오브젝트에 연결된 스레드를 떼어낸다고 한다.
    thread 객체를 지우고싶을땐 detach를 한 후 지우는 방법이 있다한다.
    그외엔 joinable(); 이라는 함수를 통해 확인 후 지우는 방법도 있다한다.
    */
    
	return 0;
}

 

  • lambda 형식으로 thread 사용가능.

    lambda 형식?
    [captures](parameters) -> return type { body }
    // <참고>
    // [captures]에서 &(참조)로 받으면 lambda내에서 변수 값을 변경할 수 있다.
    // 하지만, 복사로 받는다면 lambda내에서 값을 변경할 수 없다.
    
    ex)
    thread Thread([]()
    {
        body...
    }
    )
    

 

mutex

#include <iostream>

using namespace std;

int main()
{
    thread Thread1([] (){
         for (int cnt =0; cnt < 1000; ++cnt)
			cout << "thread function" << cnt << endl;
    });
   	
    thread Thread2([](){
  		 for (int cnt =0; cnt < 1000; ++cnt)
			cout << "thread function" << cnt << endl;
    });
    
    ...
        
    return 0;
}

위와 같을때, 여러 쓰레드에서 cout(공유자원)을 모두 참조하게된다.

이 현상을 data-race라 한다.

해결하기위해서 mutex를 쓸 수 있다.

    #incude <mutex>
    using namespace std;
    
    mutex mtx_lock;
    
    thread Thread1([] (){
         for (int cnt =0; cnt < 1000; ++cnt)
         	 mtx_lock.lock();
			cout << "thread function" << cnt << endl;
			mtx_lock.unlock();
    });

위처럼 공유자원에대해 lock, unlock 함으로써 다른 쓰레드에서 접근하지 못하게 해준다.

(try_lock도 있다. 참고하자)

하지만 lock, unlock을 자주 남발하면 속도가 굉장히 느려질것이다.

 

간단한 증가,증감 연산경우에는 atomic을 사용할 수 있다.

 

atomic

#include <iostream>
#include <atomic>

using namespace std;

int main()
{
    atomic<int> at =1; //<type>
    at.fetch_add(1);
    
    return 0;
}

atomic 으로 변수를 선언해준다.

atomic으로 선언된 변수는 초기에만 값을 대입할 수 있다. 이후에는 대입이 불가능하다.

또, atomic 변수가 동작하고 있는동안에는 다른 스레드에서 접근이 불가능하다.

(mutex.lock, unlock()을 fetch_add() 한줄로 대신한다고 보자.)

 

 

 

반응형

'Language > C++' 카테고리의 다른 글

c++ malloc new 차이점?  (0) 2019.01.26
c++ vector capacity  (0) 2019.01.08
c++ Operator  (0) 2018.12.29