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++_Multithreading_C++11_Thread Safety_Singleton - Fatal编程技术网

C++ 什么使单线程不安全?

C++ 什么使单线程不安全?,c++,multithreading,c++11,thread-safety,singleton,C++,Multithreading,C++11,Thread Safety,Singleton,我在某个地方读到一个单身汉是不安全的。我想知道为什么会这样。如果我有这样一个单例对象: class singleton final { public: static singleton& instance() { static singleton unique; return unique; } private: singleton() = default; singleton(singleton const&

我在某个地方读到一个单身汉是不安全的。我想知道为什么会这样。如果我有这样一个单例对象:

class singleton final
{
public:
    static singleton& instance()
    {
        static singleton unique;
        return unique;
    }
private:
    singleton() = default;
    singleton(singleton const&) = delete;
    singleton& operator=(singleton const&) = delete;
};
singleton *p1, *p2;

auto t1 = std::thread([] { p1 = &singleton::instance(); });
auto t2 = std::thread([] { p2 = &singleton::instance(); });

t1.join();
t2.join();
bool __instance_initialized = false;
alignas(X) char __buf_instance[sizeof(X)];
// ...
X& instance()
{
    if (!__instance_initialized)
    {
        ::new(__buf_instance) X;
        __instance_initialized = true;
    }
    return *static_cast<X*>(__buf_instance);
}
如果我有这样的代码:

class singleton final
{
public:
    static singleton& instance()
    {
        static singleton unique;
        return unique;
    }
private:
    singleton() = default;
    singleton(singleton const&) = delete;
    singleton& operator=(singleton const&) = delete;
};
singleton *p1, *p2;

auto t1 = std::thread([] { p1 = &singleton::instance(); });
auto t2 = std::thread([] { p2 = &singleton::instance(); });

t1.join();
t2.join();
bool __instance_initialized = false;
alignas(X) char __buf_instance[sizeof(X)];
// ...
X& instance()
{
    if (!__instance_initialized)
    {
        ::new(__buf_instance) X;
        __instance_initialized = true;
    }
    return *static_cast<X*>(__buf_instance);
}

p1
p2
是否可能指向两个不同的
singleton
实例?如果
unique
static
,那么它的“静态”性质在完全初始化之前不会生效吗?如果是这样,这是否意味着可以同时访问静态对象的初始化,从而允许创建多个静态对象?

在C++98/03中,本地静态文件:

X& instance()
{
    static X x;
    return x;
}
这意味着您的代码将执行以下操作:

class singleton final
{
public:
    static singleton& instance()
    {
        static singleton unique;
        return unique;
    }
private:
    singleton() = default;
    singleton(singleton const&) = delete;
    singleton& operator=(singleton const&) = delete;
};
singleton *p1, *p2;

auto t1 = std::thread([] { p1 = &singleton::instance(); });
auto t2 = std::thread([] { p2 = &singleton::instance(); });

t1.join();
t2.join();
bool __instance_initialized = false;
alignas(X) char __buf_instance[sizeof(X)];
// ...
X& instance()
{
    if (!__instance_initialized)
    {
        ::new(__buf_instance) X;
        __instance_initialized = true;
    }
    return *static_cast<X*>(__buf_instance);
}
但是现在一个线程可以将
\uu instance\u initialized
设置为true并开始构造
X
,并在第一个线程仍在忙于构造
X
时进行第二个线程测试并跳过
if
。然后,第二个线程将向其客户机提供未初始化的内存,直到第一个线程最终完成构造

在C++11中,更改了语言规则,因此编译器必须设置代码,使第二个线程不能运行过去,也不能开始构造
X
,直到第一个线程成功完成构造。这可能意味着第二个线程必须等待任意时间才能继续。。。直到第一根线结束。如果第一个线程在尝试构造
X
时抛出异常,那么第二个线程将醒来并尝试构造它


编译器如何完成此任务。

在C++98/03中,文件本地静态:

X& instance()
{
    static X x;
    return x;
}
这意味着您的代码将执行以下操作:

class singleton final
{
public:
    static singleton& instance()
    {
        static singleton unique;
        return unique;
    }
private:
    singleton() = default;
    singleton(singleton const&) = delete;
    singleton& operator=(singleton const&) = delete;
};
singleton *p1, *p2;

auto t1 = std::thread([] { p1 = &singleton::instance(); });
auto t2 = std::thread([] { p2 = &singleton::instance(); });

t1.join();
t2.join();
bool __instance_initialized = false;
alignas(X) char __buf_instance[sizeof(X)];
// ...
X& instance()
{
    if (!__instance_initialized)
    {
        ::new(__buf_instance) X;
        __instance_initialized = true;
    }
    return *static_cast<X*>(__buf_instance);
}
但是现在一个线程可以将
\uu instance\u initialized
设置为true并开始构造
X
,并在第一个线程仍在忙于构造
X
时进行第二个线程测试并跳过
if
。然后,第二个线程将向其客户机提供未初始化的内存,直到第一个线程最终完成构造

在C++11中,更改了语言规则,因此编译器必须设置代码,使第二个线程不能运行过去,也不能开始构造
X
,直到第一个线程成功完成构造。这可能意味着第二个线程必须等待任意时间才能继续。。。直到第一根线结束。如果第一个线程在尝试构造
X
时抛出异常,那么第二个线程将醒来并尝试构造它


编译器如何实现这一点。

在C++11中,静态初始化的规则已更改为线程安全。@Jarod42我知道,但我想了解为什么它一开始不是线程安全的。仍然有一个对象,但初始化不是线程安全的:可能会返回尚未初始化的对象(对于双重初始化也不确定)单例初始化可能是线程不安全的,具体取决于它的实现方式,而单例对象本身可能是线程不安全的,具体取决于类的实现方式。如上所述,您读取的内容不正确。@Jarod42为什么不初始化它?静态初始化规则在C++11中已更改为线程安全。@Jarod42我知道,但我想了解为什么一开始它不是线程安全的。仍然有一个对象,但初始化不是线程安全的:可能会返回一个尚未初始化的对象(也不确定是否进行双重初始化)单例初始化可能是线程不安全的,具体取决于它的实现方式,而单例对象本身可能是线程不安全的,具体取决于类的实现方式。如上所述,您读到的内容是错误的。@Jarod42为什么不初始化?现在非常合理。谢谢。现在非常合理。谢谢。