c++ - 如何在不使用 <mutex> 的情况下在 C++11 中实现多线程安全单例

标签 c++ multithreading c++11 singleton atomic

现在 C++11 具有多线程,我想知道在不使用互斥体的情况下实现延迟初始化单例的正确方法是什么(出于性能原因)。 我想出了这个,但是我不太擅长编写无锁代码,所以我正在寻找一些更好的解决方案。

// ConsoleApplication1.cpp : Defines the entry point for the console application.
//
# include <atomic>
# include <thread>
# include <string>
# include <iostream>
using namespace std;
class Singleton
{

public:
    Singleton()
    {
    }
static  bool isInitialized()
    {
        return (flag==2);
    }
static  bool initizalize(const string& name_)
    {
        if (flag==2)
            return false;// already initialized
        if (flag==1)
            return false;//somebody else is initializing
        if (flag==0)
        {
            int exp=0;
            int desr=1;
            //bool atomic_compare_exchange_strong(std::atomic<T>* obj, T* exp, T desr)
            bool willInitialize=std::atomic_compare_exchange_strong(&flag, &exp, desr);
            if (! willInitialize)
            {
                //some other thread CASed before us
                std::cout<<"somebody else CASed at aprox same time"<< endl;
                return false;
            }
            else 
            {
                initialize_impl(name_);
                assert(flag==1);
                flag=2;
                return true;
            }
        }
    }
static void clear()
{
    name.clear();
    flag=0;
}
private:
static  void initialize_impl(const string& name_)
{
        name=name_;
}
static  atomic<int> flag;
static  string name;
};
atomic<int> Singleton::flag=0;
string Singleton::name;
void myThreadFunction()
{
    Singleton s;
    bool initializedByMe =s.initizalize("1701");
    if (initializedByMe)
        s.clear();

}
int main()
{
    while (true)
    {
        std::thread t1(myThreadFunction);
        std::thread t2(myThreadFunction);
        t1.join();
        t2.join();
    }
    return 0;
}

注意 clear() 只是为了测试,真正的单例不会有这个功能。

最佳答案

C++11 消除了手动锁定的需要。如果静态局部变量已被初始化,则并发执行将等待。

§6.7 [stmt.dcl] p4

If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.

因此,简单的 static 函数是这样的:

static Singleton& get() {
  static Singleton instance;
  return instance;
}

这在 C++11 中可以正常工作(当然,只要编译器正确实现了标准的那一部分)。


当然,真正的正确答案是使用单例,句号。

关于c++ - 如何在不使用 <mutex> 的情况下在 C++11 中实现多线程安全单例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11711920/

相关文章:

c++ - 非常量元素 initializer_list 类

c++ - 如何知道单位的平面尺寸?

c# - .NET 中的多线程绘图?

python - 带有类列表和成员函数的线程池

c++11:从模板函数构建 std::tuple

c++ - 在不知道大小的情况下传递二维数组?

c++ - 为什么代码打印所有第一个索引?

java - 从 ActionPerformed 调用方法并在主线程上运行它

c++ - 没有模板参数的可变参数模板函数

c++ - std::make_shared 是否执行值初始化(GCC 和 clang 不同意)?