728x90
스레드 로컬 스토리지(Thread Local Storage, TLS)는 각 스레드가 독립적으로 사용할 수 있는 메모리 영역을 지칭한다. 이는 멀티스레드 환경에서 각 스레드가 고유한 데이터를 보유하고 유지할 수 있도록 한다. 일반적으로 전역 변수는 여러 스레드에 의해 공유되지만, TLS를 사용하면 각 스레드가 자체 데이터 복사본을 가질 수 있다. 이렇게 들으면 어렵지만 멀티쓰레드 환경에서 중요한 것 중 하나가 쓰레드를 여러 개 사용하는 것 과 일감이 적절하게 분배되는 것이다. 일감이 몰리면 자연적으로 경합이 일어나게 되기 때문이다. 그래서 쓰레드들이 공유하는 힙과 데이터 영역에서 데이터를 꺼내올 때 꺼내올때만 락을 잡고 데이터를 큼지막하게 TLS 에 가지고 오면 그다음엔 굳이 데이터 영역에 가지 않고 TLS를 통해 데이터를 얻어온다고 생각하면 편하다. 각 스레드 마다 가지고 있는 스택 메모리 영역은 함수를 호출하거나 하기때문에 뭔가를 저장하거나 하는 건 위험한 생각이다. TSL 는 나만의 전역 메모리 같은 느낌이라고 생각하면 좋다.
TLS를 사용하는 이유:
- 스레드별 고유한 상태 관리: 각 스레드가 고유한 데이터를 유지하고 관리할 수 있다. 이를 통해 스레드 간 충돌을 피하고 데이터의 일관성을 유지할 수 있다.
- 전역 변수와의 분리: 전역 변수를 사용할 때 발생할 수 있는 스레드 간의 경쟁 조건을 피할 수 있다. TLS를 사용하면 전역 변수와 관련된 이러한 문제를 해결할 수 있다.
- 성능 향상: TLS를 사용하면 스레드가 자주 사용하는 데이터에 대한 접근이 더 빠를 수 있다. 이는 해당 데이터가 스레드의 로컬 메모리에 저장되어 있기 때문에 발생한다.
TLS를 사용하는 언어 및 라이브러리에는 다양한 방법이 있다. 예를 들어, C++11부터는 thread_local 키워드를 사용하여 TLS를 선언할 수 있다.
TLS를 사용할 때 주의할 점은 각 스레드에서 공유되지 않는 데이터를 사용하는 것이므로 메모리 누수나 일관성 문제가 발생하지 않도록 주의해야 한다. 또한 TLS를 오용하여 과도하게 많은 데이터를 저장하는 것도 성능 문제를 초래할 수 있다.
아래는 쓰레드마다 각각 다른 아이디를 가지게 하고싶다라고 할때 TLS 를 이용해 구현해 본 것이다.
#include <iostream>
#include <atomic>
#include <vector>
#include <mutex>
using namespace std;
thread_local int LThreadId = 0;
void ThreadMain(int _iThreadId)
{
LThreadId = _iThreadId;
while (true)
{
cout << "My Id is " << LThreadId << endl;
this_thread::sleep_for(1s);
}
}
int main()
{
vector<thread> threads;
for (int i = 0; i < 10; ++i)
{
int threadId = i + 1;
threads.push_back(thread(ThreadMain, threadId));
}
for (thread& t : threads)
t.join();
return 0;
}
728x90
댓글