앞선 글에서는 동기화 기법인 뮤텍스(Mutex)와 세마포(Semaphore)의 기본 개념을 살펴보았다.
프로세스 동기화 기법 — 뮤텍스 락과 세마포
앞선 글에서는 여러 프로세스나 스레드가 공유 자원에 동시에 접근할 때 발생하는 레이스 컨디션과, 이를 막기 위한 프로세스 동기화의 필요성을 살펴보았다. 이번 글에서는 대표적인 동기화
lo88ng.tistory.com
그런데 C++ 코드를 작성하다 보면 뮤텍스를 사용하는 방법이 하나만 있는 것은 아니다.
- C++ 표준 라이브러리에는 std::mutex가 있다.
- Windows에서는 다음과 같은 API를 통해 Mutex 객체를 직접 생성할 수도 있다.
둘 다 상호 배제를 구현하지만, 사용 범위와 추상화 수준이 다르다.
이번 글에서는 먼저 API가 무엇인지 알아보고, std::mutex와 Windows API Mutex의 차이를 비교한다.
API란?
API(Application Programming Interface)는 프로그램이 다른 프로그램, 라이브러리 또는 운영체제가 제공하는 기능을 사용할 수 있도록 만들어진 사용 규칙과 접점이다.
예를 들어 프로그램에서 파일을 열거나, 창을 생성하거나, 스레드를 재우려면 운영체제의 기능이 필요하다.
이때, 프로그램이 운영체제 내부 코드를 직접 조작하는 대신, 운영체제가 제공하는 함수를 호출한다.
Application
↓ API 호출
Operating System
↓
요청된 기능 수행
Windows에서 파일을 열 때는 다음과 같은 API를 사용할 수 있다.
CreateFile()
ReadFile()
WriteFile()
CloseHandle()
프로세스 / Mutex 를 생성할 때는 다음 API를 사용할 수 있다.
CreateProcess()
CreateMutex()
외에도, 매개변수, 반환값, 자료형, 구조체, 상수, 오류 처리 규칙, 호출 순서 등이 모두 포함될 수 있다.
즉 API는 단순히 “쓸 수 있는 함수 목록”이라기보다, 외부 기능을 사용할 수 있도록 정해진 인터페이스 전체라고 볼 수 있다.
이처럼 Windows가 프로그램에 제공하는 함수와 자료형의 집합을 보통 Windows API 또는 Win32 API라고 부른다.
std::mutex
C++ 표준 라이브러리의 std::mutex는 C++ 표준 라이브러리가 제공하는 상호 배제 도구다.
다음 헤더를 포함해 사용한다.
#include <mutex>
기본적인 사용 형태는 다음과 같다.
lock()을 호출하면 현재 스레드가 뮤텍스의 소유권을 획득할 때까지 대기하고, unlock()을 호출하면 소유권을 해제한다.
#include <iostream>
#include <mutex>
#include <thread>
int Sum = 0;
std::mutex SumMutex;
void Increase()
{
for (int i = 0; i < 100000; ++i)
{
SumMutex.lock();
++Sum;
SumMutex.unlock();
}
}
단, 실행 중 예외가 발생하거나 함수가 중간에 종료되면 정상적으로 unlock()이 호출되지 않을 수 있기에 일반적으로 std::lock_guard를 사용한다.
void Increase()
{
for (int i = 0; i < 100000; ++i)
{
std::lock_guard<std::mutex> Lock(SumMutex);
++Sum;
}
}
lock_guard는 객체가 생성될 때 Mutex를 잠그고, 스코프를 벗어날 때 자동으로 해제한다.
이러한 방식을 RAII(Resource Acquisition Is Initialization)라고 한다.
특징
- C++ 표준 라이브러리에 포함된다.
- 운영체제에 종속되지 않는 인터페이스를 제공한다.
- 주로 같은 프로세스 내부의 여러 스레드를 동기화하는 데 사용한다.
- lock_guard, unique_lock 등의 RAII 객체와 함께 사용할 수 있다.
- 직접 Handle을 관리할 필요가 없다.
Windows API Mutex
Windows API Mutex는 Windows 운영체제가 제공하는 Mutex 커널 객체다.
일반적으로 다음 함수를 사용한다.
CreateMutex() Mutex 생성
WaitForSingleObject() Mutex 획득 대기
ReleaseMutex() Mutex 해제
CloseHandle() Handle 정리
기본적인 코드는 다음과 같다.
#include <Windows.h>
HANDLE MutexHandle = nullptr;
void InitializeMutex()
{
MutexHandle = CreateMutex(
nullptr,
FALSE,
nullptr
);
}
CreateMutex()의 반환값은 HANDLE이다.
이 Handle은 Windows가 관리하는 Mutex 객체를 프로그램에서 참조하기 위한 값이다.
Windows API Mutex 사용 예시
Windows API Mutex의 대표적인 활용 사례는 프로그램 중복 실행 방지다.
첫 번째 프로그램이 이름 있는 Mutex를 생성하고, 두 번째 프로그램이 같은 이름의 Mutex를 생성하려 할 때 이미 존재하는지 확인한다. 이미 존재한다면 다른 인스턴스가 실행 중이라고 판단하고 종료할 수 있다.
#include <Windows.h>
#include <iostream>
int main()
{
HANDLE MutexHandle = CreateMutex(
nullptr,
TRUE,
TEXT("MyProgramSingleInstanceMutex")
);
if (MutexHandle == nullptr)
{
std::cout << "Mutex 생성 실패\n";
return 1;
}
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
std::cout << "이미 프로그램이 실행 중입니다.\n";
CloseHandle(MutexHandle);
return 0;
}
std::cout << "프로그램 실행 중...\n";
std::cin.get();
ReleaseMutex(MutexHandle);
CloseHandle(MutexHandle);
return 0;
}
정리
std::mutex와 Windows API Mutex는 모두 하나의 공유 자원에 여러 실행 흐름이 동시에 접근하지 못하도록 막는다.
하지만 사용 목적은 조금 다르다.
std::mutex
├─ C++ 표준 라이브러리
├─ 플랫폼 독립적
├─ 스레드 간 동기화
└─ 사용이 간단함
Windows API Mutex
├─ Windows 전용
├─ 커널 객체
├─ 프로세스 간 동기화 가능
└─ Handle을 직접 관리
일반적인 C++ 멀티스레드 코드에서는 std::mutex를 우선 사용하고, Windows의 프로세스 간 동기화 기능이 필요할 때 Windows API Mutex를 사용하면 된다.
std::mutex는 C++에서 간편하게 사용하는 하나의 프로세스 내 스레드 동기화 도구이고, Windows API Mutex는 Windows 기능을 직접 사용해 스레드와 프로세스를 동기화하는 도구다.
'CS > 운영체제' 카테고리의 다른 글
| 교착 상태 (Deadlock) 해결법 — 예방, 회피, 검출 후 회복 (0) | 2026.07.26 |
|---|---|
| 교착 상태 (Deadlock) — 자원 할당 그래프와 네 가지 발생조건 (0) | 2026.07.26 |
| 프로세스 동기화 기법 — 뮤텍스 락과 세마포 (0) | 2026.07.26 |
| 프로세스 동기화 — 레이스 컨디션(Race Condition) (0) | 2026.07.25 |
| 프로세스 간 통신 (Inter-Process Communication) (0) | 2026.07.25 |