Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C++;11?_C++_Multithreading_C++11_Thread Local_Thread Local Storage - Fatal编程技术网

C++ 在C++;11?

C++ 在C++;11?,c++,multithreading,c++11,thread-local,thread-local-storage,C++,Multithreading,C++11,Thread Local,Thread Local Storage,我对C++11中的thread\u local的描述感到困惑。我的理解是,每个线程在函数中都有唯一的局部变量副本。所有线程都可以访问全局/静态变量(可能使用锁进行同步访问)。而thread\u local变量对所有线程都可见,但只能由定义它们的线程修改?对吗 线程本地存储持续时间是一个术语,用于指看起来是全局或静态存储持续时间的数据(从使用它的函数的角度来看),但实际上,每个线程有一个副本 它添加到当前自动(在块/函数期间存在)、静态(在程序持续时间内存在)和动态(在分配和释放之间的堆上存在)

我对C++11中的
thread\u local
的描述感到困惑。我的理解是,每个线程在函数中都有唯一的局部变量副本。所有线程都可以访问全局/静态变量(可能使用锁进行同步访问)。而
thread\u local
变量对所有线程都可见,但只能由定义它们的线程修改?对吗

线程本地存储持续时间是一个术语,用于指看起来是全局或静态存储持续时间的数据(从使用它的函数的角度来看),但实际上,每个线程有一个副本

它添加到当前自动(在块/函数期间存在)、静态(在程序持续时间内存在)和动态(在分配和释放之间的堆上存在)

线程本地的东西在线程创建时就已经存在,并在线程停止时被处理掉

下面是一些例子

设想一个随机数生成器,其中种子必须基于每个线程进行维护。使用线程本地种子意味着每个线程获得自己的随机数序列,独立于其他线程

如果种子是随机函数中的一个局部变量,那么每次调用它时它都会被初始化,每次都给你相同的数字。如果它是一个全局线程,线程将相互干扰序列

另一个示例类似于
strtok
,其中标记化状态存储在特定于线程的基础上。这样,单个线程可以确保其他线程不会破坏其标记化工作,同时仍然能够在多次调用
strtok
时保持状态-这基本上使
strtok\r
(线程安全版本)变得多余

这两个示例都允许线程局部变量存在于使用它的函数中。在预线程化代码中,它只是函数中的一个静态存储持续时间变量。对于线程,修改为线程本地存储持续时间

另一个例子是类似于
errno
。您不希望在一个调用失败后,但在检查变量之前,单独的线程修改
errno
,但您只希望每个线程有一个副本


对不同的存储持续时间说明符有一个合理的描述。

线程本地存储持续时间是一个术语,用于指看起来是全局或静态存储持续时间(从使用它的函数的角度来看)但实际上每个线程有一个副本的数据

它添加到当前自动(在块/函数期间存在)、静态(在程序持续时间内存在)和动态(在分配和释放之间的堆上存在)

线程本地的东西在线程创建时就已经存在,并在线程停止时被处理掉

下面是一些例子

设想一个随机数生成器,其中种子必须基于每个线程进行维护。使用线程本地种子意味着每个线程获得自己的随机数序列,独立于其他线程

如果种子是随机函数中的一个局部变量,那么每次调用它时它都会被初始化,每次都给你相同的数字。如果它是一个全局线程,线程将相互干扰序列

另一个示例类似于
strtok
,其中标记化状态存储在特定于线程的基础上。这样,单个线程可以确保其他线程不会破坏其标记化工作,同时仍然能够在多次调用
strtok
时保持状态-这基本上使
strtok\r
(线程安全版本)变得多余

这两个示例都允许线程局部变量存在于使用它的函数中。在预线程化代码中,它只是函数中的一个静态存储持续时间变量。对于线程,修改为线程本地存储持续时间

另一个例子是类似于
errno
。您不希望在一个调用失败后,但在检查变量之前,单独的线程修改
errno
,但您只希望每个线程有一个副本


对不同的存储持续时间说明符有合理的描述。

线程本地存储在各个方面都与静态(=全局)存储类似,只是每个线程都有对象的单独副本。对象的生命周期从线程开始(对于全局变量)或第一次初始化(对于块局部静态)开始,到线程结束(即调用
join()
时)结束

因此,只有也可以声明为
静态
的变量可以声明为
线程_局部
,即全局变量(更准确地说,变量“在命名空间范围”)、静态类成员和块静态变量(在这种情况下,隐含了
静态

例如,假设您有一个线程池,并且想知道您的工作负载平衡得有多好:

thread_local Counter c;

void do_work()
{
    c.increment();
    // ...
}

int main()
{
    std::thread t(do_work);   // your thread-pool would go here
    t.join();
}
这将打印线程使用情况统计信息,例如使用如下实现:

struct Counter
{
     unsigned int c = 0;
     void increment() { ++c; }
     ~Counter()
     {
         std::cout << "Thread #" << std::this_thread::id() << " was called "
                   << c << " times" << std::endl;
     }
};
结构计数器
{
无符号整数c=0;
void increment(){++c;}
~Counter()
{

std::cout线程本地存储在各个方面都与静态(=全局)存储类似,只是每个线程都有一个单独的对象副本。对象的生命周期从线程开始(对于全局变量)或第一次初始化(对于块本地静态)开始,到线程结束(即调用
join()
时)结束

因此,只有也可以声明为
静态
的变量可以声明为
线程本地
,即全局变量(更准确地说,变量“在命名空间范围”)、静态类成员和块静态变量(在
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;
}
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;
}
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();
}