반응형

간단한 멀티 스레드와 뮤텍스 사용 예를 확인해 보자.

 

뮤텍스를 사용하지 않은 멀티스레드.

#include <iostream>
#include <thread>

void counter(int id, int max) {
	for (int i = 0; i < max; i++) {
		std::cout << "id: " << id << ", : " << i << std::endl;
		std::this_thread::sleep_for(std::chrono::seconds(1));	// 1초 대기
	}
}

int main() {
	std::thread t1(counter, 1, 10);
	std::thread t2(counter, 2, 10);

	t1.join();
	t2.join();

	return 0;
}

 

cout 출력 도중 컨텍스트 스위칭이 발생하며 출력이 엉망이 되어 버렸다.

 

뮤텍스를 사용한 멀티스레드.

#include <iostream>
#include <thread>
#include <mutex>

std::mutex m;

void counter(int id, int max) {
	for (int i = 0; i < max; i++) {
		m.lock();
		std::cout << "id: " << id << ", : " << i << std::endl;
		m.unlock();
		std::this_thread::sleep_for(std::chrono::seconds(1));
	}
}

int main() {
	std::thread t1(counter, 1, 10);
	std::thread t2(counter, 2, 10);

	t1.join();
	t2.join();

	return 0;
}

 

출력이 깔끔하다.

 

하지만 위 코드에 나오는 뮤텍스의 lock(), unlock()를 직접 호출하면 안 된다. 뮤텍스 락은 일종의 리소스이기 때문에 거의 대부분 RAII 원칙에 따라 독점적으로 획득된다. 뮤텍스에 락을 정확히 걸거나 해제하는 작업을 쉽게 처리할 수 있는 lock_guard, unique_lock 등의 락 클래스를 사용하자.

 

lock_guard를 사용한 뮤텍스 멀티 스레드.

#include <iostream>
#include <thread>
#include <mutex>

std::mutex m;

void counter(int id, int max) {
	for (int i = 0; i < max; i++) {
		{
			// 락이 필요한 블럭
			std::lock_guard lock(m);
			std::cout << "id: " << id << ", : " << i << std::endl;
		}
		std::this_thread::sleep_for(std::chrono::seconds(1));
	}
}

int main() {
	std::thread t1(counter, 1, 10);
	std::thread t2(counter, 2, 10);

	t1.join();
	t2.join();

	return 0;
}

 

깔끔하고 안전한 출력.

 

반응형
Posted by J-sean
: