• ACE vs Boost: Singleton的实现


    以前曾经讨论过Singleton的实现,这次在对照ACE和Boost代码的时候,又重新审视了一下二者对Singleton不同的实现。其间的差别也体现了不同的编程哲学:ACE的实现更加偏重多线程中的安全和效率问题;Boost的实现则偏重于使用语言自身的特性满足Singleton模式的基本需求。

    o ACE的实现

    Douglas C. Schmidt在Double-Checked Locking: An Optimization Pattern for Efficiently Initializing and Accessing Thread-safe Objects一文中对double-check lock(一般译为双检锁)进行了详细的阐述。

    ACE的Singleton使用Adapter模式实现对其他类的适配,使之具有全局唯一的实例。由于C++标准并非明确指定全局静态对象的初始化顺序,ACE使用double-check lock保证线程安全,并使之不受全局静态对象初始化顺序的影响,同时也避免了全局静态实现方式的初始化后不使用的开销。

    如果你能够准确的区分以下三种实现的弊端和隐患,对double-check lock也就有了足够的了解。

    // -------------------------------------------
    class Singleton
    {
    public:
        static Singleton *instance (void)
        {
            // Constructor of guard acquires
            // lock_ automatically.
            Guard<Mutex> guard (lock_);
            // Only one thread in the
            // critical section at a time.
            if (instance_ == 0)
                instance_ = new Singleton;
            return instance_;
            // Destructor of guard releases
            // lock_ automatically.
        }
    private:
        static Mutex lock_;
        static Singleton *instance_;
    };

    // ---------------------------------------------
    static Singleton *instance (void)
    {
        if (instance_ == 0) {
            Guard<Mutex> guard (lock_);
            // Only come here if instance_
            // hasn’t been initialized yet.
            instance_ = new Singleton;
        }
        return instance_;
    }

    // ---------------------------------------------
    class Singleton
    {
    public:
        static Singleton *instance (void)
        {
            // First check
            if (instance_ == 0)
            {
                // Ensure serialization (guard
                // constructor acquires lock_).
                Guard<Mutex> guard (lock_);
                // Double check.
                if (instance_ == 0)
                    instance_ = new Singleton;
            }
            return instance_;
            // guard destructor releases lock_.
        }
    private:
        static Mutex lock_;
        static Singleton *instance_;
    };

    更多详情,见Schmidt老师的原文和ACE_Singleton实现。

    o Boost的实现

    Boost的Singleton也是线程安全的,而且没有使用锁机制。当然,Boost的Singleton有以下限制(遵从这些限制,可以提高效率):

    o The classes below support usage of singletons, including use in program startup/shutdown code, AS LONG AS there is only one thread running before main() begins, and only one thread running after main() exits.

    o This class is also limited in that it can only provide singleton usage for classes with default constructors.

    // T must be: no-throw default constructible and no-throw destructible
    template <typename T>
    struct singleton_default
    {
    private:
        struct object_creator
        {
            // This constructor does nothing more than ensure that instance()
            //  is called before main() begins, thus creating the static
            //  T object before multithreading race issues can come up.
            object_creator() { singleton_default<T>::instance(); }
            inline void do_nothing() const { }
        };
        static object_creator create_object;

        singleton_default();

    public:
        typedef T object_type;

        // If, at any point (in user code), singleton_default<T>::instance()
        //  is called, then the following function is instantiated.
        static object_type & instance()
        {
            // This is the object that we return a reference to.
            // It is guaranteed to be created before main() begins because of
            //  the next line.
          static object_type obj;

          // The following line does nothing else than force the instantiation
          //  of singleton_default<T>::create_object, whose constructor is
          //  called before main() begins.
          create_object.do_nothing();

          return obj;
        }
    };
    template <typename T>
    typename singleton_default<T>::object_creator
    singleton_default<T>::create_object;

    对于多数Singleton使用,Boost提供的版本完全能够满足需求。为了效率,我们有必要对其使用作出一定的限制。

    而在多线程编程中,则有必要使用double-check lock降低频繁加锁带来的开销。

  • 相关阅读:
    嵌入式Linux学习笔记 NAND Flash控制器
    (嵌入式开发)自己写bootloader之编写第一阶段
    C_C++指针指针应用详解
    数据结构笔记-----二叉排序树和哈希表
    map方法和filter方法
    nginx服务器卡住了 解决办法
    vue-devtoools 调试工具安装
    web 本地存储(localStorage、sessionStorage)
    vux使用教程
    一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么?
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13318938.html
Copyright © 2020-2023  润新知