C ++ 11에서 thread_local은 무엇을 의미합니까?
thread_local
C ++ 11 의 설명과 혼동됩니다 . 내 이해는 각 스레드가 함수에 고유 한 로컬 변수 복사본을 가지고 있다는 것입니다. 전역 / 정적 변수는 모든 스레드에서 액세스 할 수 있습니다 (잠금을 사용하여 동기화 된 액세스 가능). 그리고 thread_local
변수는 모든 스레드에 표시되지만 정의 된 스레드에 의해서만 수정할 수 있습니까? 맞습니까?
스레드-로컬 저장 기간은 (사용하는 함수의 관점에서) 겉보기에 글로벌 또는 정적 저장 기간 인 데이터를 가리키는 데 사용되는 용어이지만 실제로는 스레드 당 하나의 사본이 있습니다.
현재 자동 (블록 / 함수 동안 존재), 정적 (프로그램 기간 동안 존재) 및 동적 (할당과 할당 해제 사이의 힙에 존재)에 추가됩니다.
스레드 로컬 인 것은 스레드 생성시 존재하게되며 스레드가 중지되면 폐기됩니다.
다음은 몇 가지 예입니다.
시드가 스레드 단위로 유지되어야하는 난수 생성기를 생각해보십시오. 스레드 로컬 시드를 사용한다는 것은 각 스레드가 다른 스레드와 독립적으로 자체 난수 시퀀스를 가져옴을 의미합니다.
시드가 랜덤 함수 내의 지역 변수 인 경우 호출 할 때마다 초기화되어 매번 동일한 숫자를 제공합니다. 글로벌 인 경우 스레드는 서로의 시퀀스를 방해합니다.
또 다른 예는 strtok
토큰 화 상태가 스레드 별 기준으로 저장되는 것과 같습니다 . 이렇게하면 단일 스레드가 다른 스레드가 토큰 화 노력을 망치지 않도록 할 수 있으며 동시에 여러 호출을 통해 상태를 유지할 수 있습니다. strtok
이것은 기본적으로 strtok_r
(스레드 안전 버전) 중복을 렌더링합니다 .
이 두 예제 모두 스레드 로컬 변수 가이를 사용하는 함수 내에 존재하도록 허용 합니다. 미리 스레드 된 코드에서는 단순히 함수 내의 정적 저장 기간 변수 일 것입니다. 스레드의 경우 스레드 로컬 저장 기간으로 수정됩니다.
또 다른 예는 errno
. errno
호출 중 하나가 실패한 후 변수를 확인하기 전에 별도의 스레드가 수정되는 것을 원하지 않지만 스레드 당 하나의 복사본 만 필요합니다.
이 사이트 에는 다양한 저장 기간 지정자에 대한 합리적인 설명 이 있습니다 .
변수 thread_local
를 선언하면 각 스레드에는 자체 복사본이 있습니다. 이름으로 참조하면 현재 스레드와 연관된 사본이 사용됩니다. 예 :
thread_local int i=0;
void f(int newval){
i=newval;
}
void g(){
std::cout<<i;
}
void threadfunc(int id){
f(id);
++i;
g();
}
int main(){
i=9;
std::thread t1(threadfunc,1);
std::thread t2(threadfunc,2);
std::thread t3(threadfunc,3);
t1.join();
t2.join();
t3.join();
std::cout<<i<<std::endl;
}
이 코드는 "2349", "3249", "4239", "4329", "2439"또는 "3429"를 출력하지만 다른 것은 출력하지 않습니다. 각 스레드에는 i
에 할당되고 증가 된 다음 인쇄되는 자체 복사본이 있습니다. 실행중인 스레드 main
에는 자체 복사본이 있으며 처음에 할당 된 다음 변경되지 않은 상태로 유지됩니다. 이러한 사본은 완전히 독립적이며 각각 다른 주소를 갖습니다.
그 점에서 특별한 이름 일뿐입니다. --- thread_local
변수 의 주소를 취하면 스레드간에 자유롭게 전달할 수있는 일반 객체에 대한 일반 포인터 만 갖게됩니다. 예 :
thread_local int i=0;
void thread_func(int*p){
*p=42;
}
int main(){
i=9;
std::thread t(thread_func,&i);
t.join();
std::cout<<i<<std::endl;
}
Since the address of i
is passed to the thread function, then the copy of i
belonging to the main thread can be assigned to even though it is thread_local
. This program will thus output "42". If you do this, then you need to take care that *p
is not accessed after the thread it belongs to has exited, otherwise you get a dangling pointer and undefined behaviour just like any other case where the pointed-to object is destroyed.
thread_local
variables are initialized "before first use", so if they are never touched by a given thread then they are not necessarily ever initialized. This is to allow compilers to avoid constructing every thread_local
variable in the program for a thread that is entirely self-contained and doesn't touch any of them. e.g.
struct my_class{
my_class(){
std::cout<<"hello";
}
~my_class(){
std::cout<<"goodbye";
}
};
void f(){
thread_local my_class unused;
}
void do_nothing(){}
int main(){
std::thread t1(do_nothing);
t1.join();
}
In this program there are 2 threads: the main thread and the manually-created thread. Neither thread calls f
, so the thread_local
object is never used. It is therefore unspecified whether the compiler will construct 0, 1 or 2 instances of my_class
, and the output may be "", "hellohellogoodbyegoodbye" or "hellogoodbye".
Thread-local storage is in every aspect like static (= global) storage, only that each thread has a separate copy of the object. The object's life time starts either at thread start (for global variables) or at first initialization (for block-local statics), and ends when the thread ends (i.e. when join()
is called).
Consequently, only variables that could also be declared static
may be declared as thread_local
, i.e. global variables (more precisely: variables "at namespace scope"), static class members, and block-static variables (in which case static
is implied).
As an example, suppose you have a thread pool and want to know how well your work load was being balanced:
thread_local Counter c;
void do_work()
{
c.increment();
// ...
}
int main()
{
std::thread t(do_work); // your thread-pool would go here
t.join();
}
This would print thread usage statistics, e.g. with an implementation like this:
struct Counter
{
unsigned int c = 0;
void increment() { ++c; }
~Counter()
{
std::cout << "Thread #" << std::this_thread::id() << " was called "
<< c << " times" << std::endl;
}
};
참고URL : https://stackoverflow.com/questions/11983875/what-does-the-thread-local-mean-in-c11
'Programing' 카테고리의 다른 글
SELECT INTO OUTFILE을 사용할 때 헤더를 포함 하시겠습니까? (0) | 2020.08.13 |
---|---|
jQuery에서 인덱스로 요소 가져 오기 (0) | 2020.08.13 |
Pandas 데이터 프레임은 각 그룹의 첫 번째 행을 가져옵니다. (0) | 2020.08.13 |
RSpec에서 "should_receive"를 더 많이 말하는 방법 (0) | 2020.08.13 |
할당 및 동등성 검사가있는이 if 문이 거짓으로 평가되는 이유는 무엇입니까? (0) | 2020.08.13 |