728x90

병렬 프로그래밍을 할 때 std::mutex를 이용하여 여러개의 Thread에서 사용하는 공유 자원을 서로 침범 없이 사용할 수 있다. 하지만 lock을 사용하여 mutx에 대한 소유권을 얻은 후 unlock을 하지 않으면 Dead Lock에 빠지게 된다.


예를 들면


std::mutex.lock();


-----


if (true)

return true;


-----


std::mutex.unlock();



위와 같은 코드에서는 lock을 걸고 중간에 return을 했기 때문에 unlock을 하지 않게 된다.


이것은 코딩을 해보면 굉장히 실수하기 쉽다.


이런 실수를 방지하기 위해 C++ 11에서는 lock_guard라는 것이 나왔다.


사용 예 :


#include <iostream>

#include <thread>

#include <mutex>


typedef lock_guard<std::mutex> LockMutex;


int g_nCount = 0;

std::mutex g_mtxUpdate;


[ Thread 1 ]

{

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

{

LockMutex AutoLock(g_mtxUpdate);

g_nCount++;

}

}


[ Thread 2 ]

{

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

{

LockMutex AutoLock(g_mtxUpdate);

g_nCount++;

}

}


이렇게 사용하면 된다.


이것은 continue, return, 혹은 괄호의 끝을 만나게 되면 자동으로 unlock을 시켜준다.


-------------------------------------------------------------------------------------------


다음은 try_lock()이다.


원래 lock()은 다른 스레드에서 lock()이 걸려있다면 unlock()이 될 때까지 기다리게 된다.


하지만 try_lock()은 다른 스레드에서 lock()이 걸려있다면, false를 리턴하며 빠져나온다. 즉 다른 스레드에서 lock이 걸려 


자원을 사용할 수 없을 때에는 다른 일을 하고 싶을 때 사용하면 된다.


-------------------------------------------------------------------------------------------


지정한 시간 동안만 락을 시도하게 할 수도 있다. 이것을 timed_mutex 라고 부른다.


timed_mutex의 종류 중 하나인 try_lock_for()를 이용하여 지정된 시간동안 lock()을 시도하게 할 수 있다.


이 함수는 특정 시간 동안만 시도하고 성공하지 못하면 try_lock 호출을 멈추고 빠져나오길 바랄 때 사용하면 된다.


사용 예 :


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

{

----


mutex.unlock();

}


-------------------------------------------------------------------------------------------


Mutex의 lock 멤버 함수의 설명을 보면 lock을 호출한 Thread에서 unlock을 호출하지 않고 다시 lock을 호출하면 알 수 없는 동작을 한다고 되어 있다.


실제로 동작시켜보면 프로그램이 죽어버리는 현상을 겪을 수 있을 것이다.


그럴 때에는 recursive_mutex를 사용하면 된다. 이 Mutex는 같은 Thread에서 lock을 건 후 바로 lock을 걸어도 괜찮다. 


단, lock을 호출한 횟수만큼 unlock을 호출해야 한다.


사용 예 :


#include <iostream>

#include <thread>

#include <mutex>


typedef lock_guard<std::recursive_mutex> RecursiveLockMutex;


std::recursive_mutex g_mtx;


[ CheckFunction ]

{

RecursiveLockMutex autoLock(g_mtx);


------

}


[ AddFunction ]

{

RecursiveLockMutex autoLock(g_mtx);


CheckFunction();


----------

}


위의 예제 코드를 보면 알 수 있듯이 사용방법은 간단하다. std::mutex -> std::recursive_mutex로 바꾸기만 하면된다.


-------------------------------------------------------------------------------------------





ps. Windows에서 std::mutex는 내부적으로 Critical Section API를 이용한다.

728x90

'Basic Programming > C++ 11' 카테고리의 다른 글

C++11 - std::thread  (0) 2016.12.02
C++11 - "default" and "delete" keyword  (0) 2016.11.29
C++11 - nullptr  (0) 2016.02.26
C++11 - enum  (0) 2016.02.26
C++11 - range based for  (0) 2016.02.25

+ Recent posts