Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.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++_Multithreading_C++11_Thread Local Storage - Fatal编程技术网

C++ 线程局部变量的初始化

C++ 线程局部变量的初始化,c++,multithreading,c++11,thread-local-storage,C++,Multithreading,C++11,Thread Local Storage,我最近使用了一个对象,其目的是将内存作为单例进行分配和释放。差不多 class MyValue { // ... static Allocator& GetAllocator() { static Allocator allocator; return allocator; } // ... }; 我后来意识到Allocator不是线程安全的:当多个线程同时使用同一个分配器时,偶尔会发生奇怪的事情,导致断言和分段错误 解决方案:为不同的线程使用不

我最近使用了一个对象,其目的是将内存作为单例进行分配和释放。差不多

class MyValue
{
  // ...

  static Allocator& GetAllocator()
  {
    static Allocator allocator;
    return allocator;
  }

  // ...
};
我后来意识到
Allocator
不是线程安全的:当多个线程同时使用同一个分配器时,偶尔会发生奇怪的事情,导致断言和分段错误

解决方案:为不同的线程使用不同的分配器:

class MyValue
{
  // ...

  static Allocator& GetAllocator()
  {
    thread_local static Allocator allocator;
    return allocator;
  }

  // ...
};
太棒了!我的问题解决了!只有一个问题: 即使大多数线程不使用此变量,我的分配器变量是否会在每次创建线程时初始化?

分配器的初始化可能是一项繁重的操作,因此我希望它只在实际需要时才初始化,而不是在每个线程中初始化

我读到
thread\u local
变量由每个线程分配。这是否意味着它们也被建造?这种分配(或构造)是针对创建的每个线程系统地进行的,还是仅针对使用它的线程

我隐约记得在一门课程中听说,关于线程和线程本地存储的大多数细节都依赖于平台。如果是这样的话,我对Linux和FreeBSD特别感兴趣


相关(有趣的阅读,但我在那里找不到答案):


每次调用
GetAllocator()
时,我可以给您一个解决方案,检查它是否创建了一个类型为
Allocator
的新对象。只需调用此方法至少5次,并检查所有返回对象的地址。如果所有返回对象的地址都不同,那么它在每次调用中都会创建不同的对象;如果不是,那么每次调用
GetAllocator()

时它都会返回相同对象的地址。我可以给您一个解决方案,检查它是否在每次调用
GetAllocator()时都会创建一个类型为
Allocator
的新对象
。只需调用此方法至少5次,并检查所有返回对象的地址。如果所有返回对象的地址都不同,则是,它在每次调用中创建不同的对象;如果不是,则每次调用
GetAllocator()

[basic.stc.thread]状态时,它只返回同一对象的地址

  • 使用
    thread\u local
    关键字声明的所有变量都具有线程存储持续时间。这些实体的存储应在创建它们的线程期间持续。每个线程都有一个不同的对象或引用,使用声明的名称是指与当前线程关联的实体

  • 具有线程存储持续时间的变量应在其第一次odr使用(6.2)之前初始化,如果构造,应在线程退出时销毁

  • 因此,您将在每个线程中获得对象的存储空间。我们还有[stmt.dcl]/4声明

    控件第一次通过其声明时,执行具有静态存储持续时间(6.7.1)或线程存储持续时间(6.7.2)的块作用域变量的动态初始化;此类变量在初始化完成时被视为已初始化

    因此,如果我们到达声明,那么对象将被初始化,如果它有一个构造函数,它将被调用

    如果我们把这一切放在一起,你将有一个构造函数和析构函数调用的数量等于实际到达的线程数量

    thread_local static Allocator allocator;
    

    [basic.stc.thread]状态

  • 使用
    thread\u local
    关键字声明的所有变量都具有线程存储持续时间。这些实体的存储应在创建它们的线程期间持续。每个线程都有一个不同的对象或引用,使用声明的名称是指与当前线程关联的实体

  • 具有线程存储持续时间的变量应在其第一次odr使用(6.2)之前初始化,如果构造,应在线程退出时销毁

  • 因此,您将在每个线程中获得对象的存储空间。我们还有[stmt.dcl]/4声明

    控件第一次通过其声明时,执行具有静态存储持续时间(6.7.1)或线程存储持续时间(6.7.2)的块作用域变量的动态初始化;此类变量在初始化完成时被视为已初始化

    因此,如果我们到达声明,那么对象将被初始化,如果它有一个构造函数,它将被调用

    如果我们把这一切放在一起,你将有一个构造函数和析构函数调用的数量等于实际到达的线程数量

    thread_local static Allocator allocator;
    

    您确定应该使用
    静态分配器GetAllocator()
    而不是
    静态分配器&GetAllocator()
    ?singleton模式是latterAlso,在C++11中,thread_local是什么意思?这似乎回答了您的问题:线程本地的东西在线程创建时就存在了,当线程停止时就被处理掉了。i、 e.,构建和破坏@NathanOliver的可能复制品:好的观点。对,它返回一个l值引用。我将在问题中更正此问题。您确定应该使用
    静态分配器GetAllocator()
    而不是
    静态分配器&GetAllocator()
    ?singleton模式是latterAlso,在C++11中,thread_local是什么意思?这似乎回答了您的问题:线程本地的东西在线程创建时就存在了,当线程停止时就被处理掉了。i、 e.,构建和破坏@NathanOliver的可能复制品:好的观点。对,它返回一个l值引用。我将在问题中纠正这一点。你提出的实证方法是明确的,但我想理解理论。我有足够的经验,不再盲目相信简单实验的结果是揭示复杂系统背后真相的一种方式……你提出的实证方法是明确的