如何在C ++ 11中实现多线程安全单例,而不使用< mutex> [英] How to implement multithread safe singleton in C++11 without using <mutex>

查看:105
本文介绍了如何在C ++ 11中实现多线程安全单例,而不使用< mutex>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Now that C++11 has multithreading I was wondering what is the correct way to implement lazy initialized singleton without using mutexes(for perf reasons). I came up with this, but tbh Im not really good at writing lockfree code, so Im looking for some better solutions.

// 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()只是为了测试,真正的单例不会有那个函数。

Note that clear() is just for testing, real singleton wouldnt have that function.

推荐答案

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

C++11 removes the need for manual locking. Concurrent execution shall wait if a static local variable is already being initialized.

§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 函数:

As such, simple have a static function like this:

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

这将在C ++ 11中正常工作编译器会正确实现标准的那部分。)

This will work all-right in C++11 (as long as the compiler properly implements that part of the standard, of course).

当然, >正确答案是 不使用单身,期间

Of course, the real correct answer is to not use a singleton, period.

这篇关于如何在C ++ 11中实现多线程安全单例,而不使用&lt; mutex&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆