简体   繁体   English

线程局部变量的初始化

[英]Initialization of thread-local variables

I was recently using an object whose purpose is to allocate and deallocate memory as a singleton. 我最近使用的对象的目的是分配和释放内存作为单例。 Something like 就像是

class MyValue
{
  // ...

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

  // ...
};

I realized later Allocator is not thread-safe: when multiple threads were using the same allocator concurrently, occasionally strange things were happening, causing assertions and segmentation faults. 后来我意识到Allocator不是线程安全的:当多个线程同时使用相同的分配器时,偶尔会发生奇怪的事情,导致断言和分段错误。

Solution: use different allocators for different threads: 解决方案:为不同的线程使用不同的分配器:

class MyValue
{
  // ...

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

  // ...
};

Awesome! 真棒! My problems are gone! 我的问题不见了! Just one question: Will my allocator variable be initialized every time a thread is created, even if the majority of threads won't use this variable? 只有一个问题: 每次创建一个线程时,我的allocator变量是否会被初始化,即使大多数线程不使用这个变量?

The initialization of the allocator might be heavy operation, so I would like it to be initialized only when it is actually required, not in every thread. 分配器的初始化可能是繁重的操作,所以我希望它只在实际需要时才初始化,而不是在每个线程中。

I read that thread_local variables are allocated by each thread. 我读到thread_local变量是由每个线程分配的。 Does that mean they are also constructed ? 这是否意味着他们也被建造了 And does this allocation (or construction) happen systematically for each thread that is created or just for threads that use it? 对于每个创建的线程,还是仅为使用它的线程,这种分配(或构造)是否会系统地发生?

I faintly remember hearing in a course that most details about threads and thread-local storage are platform dependent. 我依旧记得在课程中听到有关线程和线程本地存储的大多数细节都依赖于平台。 If this is the case, I'm particularly interested in Linux and FreeBSD. 如果是这种情况,我对Linux和FreeBSD特别感兴趣。


Related (interesting reads, but I could not find the answer there): 相关(有趣的读物,但我找不到答案):

[basic.stc.thread] states [basic.stc.thread]陈述

  1. All variables declared with the thread_local keyword have thread storage duration . 使用thread_local关键字声明的所有变量都具有线程存储持续时间 The storage for these entities shall last for the duration of the thread in which they are created. 这些实体的存储应持续创建它们的线程的持续时间。 There is a distinct object or reference per thread, and use of the declared name refers to the entity associated with the current thread. 每个线程有一个不同的对象或引用,声明的名称的使用是指与当前线程关联的实体。

  2. A variable with thread storage duration shall be initialized before its first odr-use (6.2) and, if constructed, shall be destroyed on thread exit. 具有线程存储持续时间的变量应在其第一次使用(6.2)之前初始化,如果构造,则应在线程退出时销毁。

So, you will get storage for the object in each thread. 因此,您将获得每个线程中对象的存储空间。 We also have [stmt.dcl]/4 that states 我们还有[stmt.dcl] / 4表示

Dynamic initialization of a block-scope variable with static storage duration (6.7.1) or thread storage duration (6.7.2) is performed the first time control passes through its declaration; 第一次控制通过其声明时,将执行具有静态存储持续时间(6.7.1)或线程存储持续时间(6.7.2)的块范围变量的动态初始化; such a variable is considered initialized upon the completion of its initialization. 这样的变量在初始化完成后被认为是初始化的。

So, if we reach the declaration then the object will be initialized and if it has a constructor, it will be called. 因此,如果我们到达声明,那么对象将被初始化,如果它有一个构造函数,它将被调用。

If we put that all together you will have a number of constructor and destructor calls equal to the number of threads that actually reach 如果我们把它们放在一起你将会有一些构造函数和析构函数调用等于实际到达的线程数

thread_local static Allocator allocator;

I can give you a solution to check whether it creates a new object of type Allocator each time you call GetAllocator() . 我可以给你一个解决方案来检查每次调用GetAllocator()时它是否创建了一个Allocator类型的新对象。 Just call this method at least 5 times and check the address of all the object return. 只需调用此方法至少5次,并检查所有对象返回的地址。 If address of all the return object are different then yes its creates different object in each call or if not it just return the address of same object each time you call GetAllocator() . 如果所有返回对象的地址不同,那么它在每次调用中创建不同的对象,或者如果不是,则每次调用GetAllocator()时它只返回相同对象的地址。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM