9

我有一个 X 类:

class X { ... }

我想做这个:

void f()
{
    thread_local static X x = ...;

    ...
}

(实际上我使用的是 gcc,所以关键字是“__thread”)

但我不能,因为你只能拥有微不足道的 thread_locals。

最好的解决方法是什么?

如果我这样做:

void f()
{
    thread_local static X* p = 0;

    if (!p)
       p = new X(...);

    X& x = *p;

    ...
}

然后:

  1. 线程退出时不会调用析构函数
  2. 不必要的动态内存分配。

更新:

这是我到目前为止所拥有的:

#include <iostream>
#include <type_traits>

using namespace std;

class X { public: X() { cout << "X::X()" << endl; }; ~X() { cout << "X::~X()" << endl; } };

void f()
{
        static __thread bool x_allocated = false;
        static __thread aligned_storage<sizeof(X),
             alignment_of<X>::value>::type x_storage;

        if (!x_allocated)
        {
                new (&x_storage) X;
                x_allocated = true;
                // add thread cleanup that calls destructor
        }

        X& x = *((X*) &x_storage);
}

int main()
{
        f();
}

这解决了动态内存分配问题。我只需要添加线程清理处理程序。有没有一种机制可以用 pthreads 做到这一点?

4

2 回答 2

6

该标准描述为与第 7.1.1 节中的其他(等)thread_local一样的存储说明符。该词的任何定义都没有限制“简单”数据类型。staticextern

该问题在C++11 之前的讨论文档 N2147中进行了简要讨论(请参阅“线程变量动态初始化”部分)。这包括对正确实施所涉及的关键问题的描述。显然 GCC 实现 ( static __thread) 还没有解决这些问题(这与 GCC 不正式支持 C++11 的事实是一致的thread_local)。

在此之前的帖子boost::thread_specfic_ptr<>中提到了一种替代方法,并在此处进行了描述。

另一种选择是使用std::thread对象来实现线程并确保每个实例都维护自己的变量副本,可能包含在unique_ptr.

于 2012-08-21T06:26:26.713 回答
6

thread_local__thread实际上,它们不是一回事。它们之间的主要区别正是您偶然发现的thread_local那个 - 允许变量为非 POD。不幸的是,这也有性能影响。有关这些性能影响的更多详细信息,请参阅此问题

于 2013-07-12T07:44:28.023 回答