Bir değişken bildirdiğinizde, thread_local
her evre kendi kopyasına sahip olur. Adına atıfta bulunduğunuzda, mevcut iş parçacığı ile ilişkili kopya kullanılır. Örneğin
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;
}
Bu kod "2349", "3249", "4239", "4329", "2439" veya "3429" çıktılar, ancak başka hiçbir şey vermez. Her iş parçacığının i
, atanan, artırılan ve ardından yazdırılan kendi kopyası vardır . İş parçacığı çalışıyormain
da başlangıçta atanan ve sonra değiştirilmeden bırakılan kendi kopyası vardır. Bu kopyalar tamamen bağımsızdır ve her birinin farklı bir adresi vardır.
Sadece bu açıdan özel olan isimdir --- eğer bir thread_local
değişkenin adresini alırsanız, o zaman normal bir nesneye normal bir göstericiniz olur, bu iplikler arasında serbestçe geçebilirsiniz. Örneğin
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;
}
Adresi i
evre işlevine aktarıldığından, bu i
durumda bile ana evreye ait olanın kopyası atanabilir thread_local
. Bu program böylece "42" çıktısını alacaktır. Bunu yaparsanız, *p
ait olduğu iş parçacığı çıktıktan sonra erişilemeyenlere dikkat etmeniz gerekir , aksi takdirde, işaret edilen nesnenin yok edildiği diğer durumlarda olduğu gibi sarkan bir işaretçi ve tanımsız davranış elde edersiniz.
thread_local
değişkenler "ilk kullanımdan önce" ilklendirilir, bu nedenle belirli bir iş parçacığına hiç dokunulmazlarsa, o zaman mutlaka ilklendirilmeleri gerekmez. Bu, derleyicilerin thread_local
programdaki her değişkeni tamamen kendi kendine yeten ve hiçbirine dokunmayan bir iş parçacığı için yapılandırmaktan kaçınmasını sağlamak içindir . Örneğin
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();
}
Bu programda 2 iş parçacığı vardır: ana iş parçacığı ve elle oluşturulan iş parçacığı. Hiçbir iş parçacığı çağırmaz f
, dolayısıyla thread_local
nesne asla kullanılmaz. Bu nedenle, derleyicinin 0, 1 veya 2 örneklerini oluşturup oluşturmayacağı belirtilmemiştir my_class
ve çıktı "", "hellohellogoodbyegoodbye" veya "hellogoodbye" olabilir.
strtok
.strtok
tek iş parçacıklı bir ortamda bile kırılır.