서버/멀티스레드

11. Thread Local Storage

광란의슈가슈가룬 2024. 7. 25. 00:23

Thread Local Storage, TLS란 스레드들이 공용으로 접근하는 힙(heap)영역과는 다르게 스레드만의 독립된 공간이다. 각 스레드마다 스택이라는 독립된 공간이 존재하지만 TLS와는 차이점이 분명히 존재한다.

 

스택은 일반적으로 함수들의 공간이라고 본다. 함수가 호출되고 종료되면서 메모리에 올라갔다 없어졌다 하는 불안정한 공간이기 때문에 전역변수와 같은 영구적으로 사용할 데이터를 저장하는 것은 위험하다.

 

따라서 TLS라는 공간이 존재하는 것인데 전역변수 같은 데이터를 저장하는데 사용되는 공간이다. 물론 각 스레드만의 독립된 공간이므로 다른 스레드에서는 전역변수에 접근할 수 없고 오로지 해당 스레드에서만 접근이 가능하다.

 

thread_local int TLS;

 TLS를 사용하는 방법은 간단하다. 변수 선언을 할 때 앞에 thread_local이라는 키워드만 붙여주면 된다.

 

#include <iostream>
#include <thread>

thread_local int LThreadId = 0;

void ThreadMain(int threadId)
{
	LThreadId = threadId;

	while (true)
	{
		cout << "Thread " << LThreadId << endl;

		this_thread::sleep_for(2s);
	}
}

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();
}

thread_local를 이용해 각 스레드마다 ID를 부여하는 간단한 코드이다. thread_local 키워드 없이 전역변수로 선언을 했을 경우 모든 스레드에서 10이라는 ID를 출력하게 될 것이다. 하지만 thread_local 키워드를 사용함으로써 각 스레드들은 LThreadId를 자신의 TLS영역으로 들고와서 사용하기 때문에 각자 다른 ID를 가지게 된다.

키워드 사용 X

키워드를 사용하지 않았을 때는 10이라는 값으로 덮어 씌워지기 때문에 최종적으로 모두 10이 된다. 출력이 이상한 것은 cout에서 데이터를 출력하는 행위가 원자적으로 일어나지 않기 때문이다.

키워드 사용 O

모든 스레드들이 자신만의 ID를 가진 것을 볼 수 있다.

 

thread_local 키워드는 위와 같이 순서대로 ID를 부여한다던가 자신만의 큐를 두어 데이터를 처리하는 등 각 스레드마다 개별로 사용되어야 할 데이터를 다루는데 유용하게 이용된다.

'서버 > 멀티스레드' 카테고리의 다른 글

13. Lock-Free Stack #1  (0) 2024.07.29
12. Lock-Based Queue/Stack  (0) 2024.07.26
10. 메모리 모델  (0) 2024.07.24
9. Future  (0) 2024.07.21
8. Condition Variable  (0) 2024.07.20