thread_local 키워드란?
thread_local은 데이터 타입(Data Type)은 아니고, 저장소 지정자(Storage Class Specifier)이다.
int, double, class와 같은 자료형이 아니라, 해당 변수를 어디에, 얼마나 오랫동안 저장할 것인지를 컴파일러에게 지시하는 키워드(keyword)이다.
thread_local로 해당 변수의 생명주기를 설정하는 것이 가능하다. 즉, thread_local 키워드를 사용해서 변수를 선언하면 해당 변수의 생명주기는 해당 스레드의 생명주기와 동일하게 설정된다.
thread_local의 핵심 개념
thread_local 키워드가 붙은 변수는 스레드 저장 수명(Thread Storage Duration)을 가진다.
- 독립된 복사본 : 각 스레드마다 해당 변수의 고유한 복사본을 별도로 가진다.
- 스레드 간 상호 간섭 없음 : A 스레드가 해당 변수를 변경해도 B 스레드에 있는 같은 이름의 변수는 전혀 영향을 받지 않는다.
- 생명주기 : 스레드가 시작할 때 생성되어서 스레드가 종료되면 소멸한다.
코드 예제
전역 변수로 생성한 local_counter 각 스레드에서 해당 변수를 참조해서 변경하지만 thread_local로 선언되어 있기 때문에 스레드별로 고유하고 독립적인 local_counter 변수를 가진다.
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
thread_local int local_counter = 0;
std::mutex mtx;
void increase_counter(int thread_id)
{
local_counter++;
local_counter++;
std::lock_guard<std::mutex> lock(mtx);
std::cout << "Thread " << thread_id << "의 local_counter 값: " << local_counter << std::endl;
}
void main()
{
std::cout << "hello, world" << std::endl;
std::thread thread1(increase_counter, 1);
std::thread thread2(increase_counter, 2);
std::thread thread3(increase_counter, 3);
thread1.join();
thread2.join();
thread3.join();
}

만약에 thread_local 키워드를 제거하면 각 스레드 별로 독립적으로 존재하는 변수가 아닌 전역 변수이기 때문에 다른 결과를 얻게 된다. 아마도 각 스레드 별로 2씩 값을 올리기 때문에 6이라는 결과가 나올 것이다.

정리하자면
- 지역 변수는 애초에 스레드 별로 독립적으로 관리된다. 각 스레드마다 별도의 스택 공간에서 관리된다.
- thread_local 키워드를 사용하는 이유는 지역 변수는 해당 함수가 끝나면 같이 소멸하기 때문
- 그렇다고 전역 변수를 쓰자니 전역 변수는 모든 스레드에서 접근이 가능하고 공유된다.
- 즉, thread_local 키워드를 사용하면 각 스레드 별로 독립적으로 사용이 가능하면서 생명주기는 전역변수와 동일해진다.
일반 지역 변수 생명 주기
지역 변수는 해당 스코프를 벗어나면 자동으로 해제된다.
void func()
{
int count = 0; // 매번 0으로 초기화됨
count++;
// 함수가 끝나면 count는 메모리에서 사라짐
}
정적 변수(static) 생명 주기
스레드 간에 공유되기 때문에 모든 스레드에서 접근이 가능하다.
void func()
{
static int count = 0; // 프로그램 시작 시 딱 한 번 생성, 프로그램 종료 시 소멸
count++;
// 함수가 끝나도 값은 살아있음 (예: 1, 2, 3...)
}
스레드 로컬 변수
static과 동일한 생명 주기를 갖지만 스레드 별로 독립적으로 관리됨
void func()
{
// 1. 값을 기억함 (static 처럼)
// 2. 하지만 스레드마다 별개임 (지역 변수 처럼)
thread_local int count = 0;
count++;
}
함께 읽으면 좋은 글
메모리 구조(Memory Structure)에 대해서
메모리 구조우리가 exe 파일을 실행하면 운영체제는 프로그램에 정의된 명령어(코드)를 바탕으로 메모리에 프로세스를 적재(Load)한다. 그리고 해당 프로세스를 위한 Code, Data, Heap, Stack 영역이 생
jettstream.tistory.com
'프로그래밍 > C++' 카테고리의 다른 글
| 바쁜 대기(Busy Waiting)에 대해서 알아보자 (0) | 2026.02.01 |
|---|---|
| 상호배제란 무엇인가? (0) | 2026.02.01 |
| RAII에 대해서 알아보자 (0) | 2026.01.26 |
| C++ 임시 객체에 대해서 (0) | 2026.01.25 |
| unique_ptr vs shared_ptr 차이는 무엇인가? (0) | 2026.01.03 |
댓글