c++ - 指向对象初始化线程安全的静态指针

标签 c++ c++11 thread-safety static-initialization

在 C++11 中,以下是线程安全的:

void someFunc()
{
    static MyObject object;
}

但是呢

void someFunc()
{
    static MyObject *ptr = new MyObject();
}

这是否是线程安全的?

正如@Nawaz 在评论中提到的那样,MyObject 构造函数可能不是线程安全的,所以让我们将问题分成几个部分:

1) 如果 ctor 是线程安全的(它不访问任何共享状态),那么这个 static MyObject *ptr = new MyObject(); 是线程安全的吗?换句话说,static int *ptr = new int(0); 是线程安全的吗?

2) 如果 ctor 不是线程安全的,但对象只是通过从不同线程调用 someFunc 创建的,并且从未在其他任何地方使用构造函数,那么这是否是线程安全的?那么安全吗?

最佳答案

是的,它是线程安全的。这源于适用于第一个示例的相同保证,即函数的并发执行将恰好初始化静态变量一次。由于静态指针必须被恰好初始化一次,并且初始化它的方式被定义为调用new,那么new和它调用的构造函数将分别被恰好调用一次。假设 new 对象的构造函数没有做任何不安全的事情,那么整个事情就是安全的。

感谢 Matthieu M. 指出了一个异常:如果初始化抛出,将在下一次(挂起或 future )调用函数时再次尝试。不过它仍然是线程安全的,因为第二次尝试要等到第一次尝试失败后才会开始。

话虽如此,看到这样的代码还是令人担忧,因为它似乎很可能会导致内存泄漏,这可能会被 valgrind 等自动化工具标记出来,因此最好以某种方式避免这种情况。即使是具有静态成员的类也可能更好,因为在程序结束之前使用要调用的特殊方法清理静态会更容易。

关于c++ - 指向对象初始化线程安全的静态指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24933452/

相关文章:

c++ - 初始化结构的二维数组

c++ - 关于 C++ 运算符 "address of"和 "scope resolution"优先级的问题

c++ - 如何让移动构造函数有意调用

c++ - 为什么在 C++11 中使用非成员开始和结束函数?

c# - volatile 关键字可以用于构建线程安全的自动清除缓存吗?

java - 如何从任何地方获取上下文?

c++ - 线程安全的延迟获取和释放

c++ - 错误 : Cannot convert 'const value_type' to 'char'

c++ - 我可以将 C++ 代码(或用 C++ 编写的库)与混合移动应用程序代码混合使用吗?

c++ - C++中的静态公共(public)值函数