简体   繁体   English

这是 Singleton 实现线程安全的吗?

[英]Is this Singleton Implementation Thread-Safe?

I've read the question and answers here , and learned that a true thread-safe singleton can be implemented with correctly placed memory barrier, which is stated here in chapter 6. I've come up with my own version of singleton implementation, by reviewing the code I've seen no memory ordering problem so far, but it differs a lot from a typical DCLP approach.我已经阅读了这里的问题和答案,并了解到可以使用正确放置的 memory 屏障来实现真正的线程安全 singleton,在第 6 章中有说明。我提出了我自己的 Z2ED5060A352961BC58 实现版本,由查看代码到目前为止,我没有看到 memory 排序问题,但它与典型的 DCLP 方法有很大不同。 Do you think this is a reliable implementation?你认为这是一个可靠的实现吗?

static std::atomic<T*> _instance;
...
Singleton* get_instance() {
    ins = _instance.load(std::memory_order_acquire);
    if (ins == nullptr) {
        T* temp = nullptr;
        {            
            std::lock_guard<std::mutex> guard(_lock);
            temp = new(std::nothrow) T;
        }

        if(!_instance.compare_exchange_strong(nullptr, temp, std::memory_order_release)) {
            delete temp;
        }
    }
    return _instance.load(std::memory_order_acquire);
}

It is hard to beat a simple很难打败一个简单的

class Singleton { ... };

Singleton* get_instance()
{
    static Singleton instance; // guaranteed to be thread safe in C++11
    return &instance;
}

Any access to the pointer after it has been returned is still not thread safe, but neither is access in your implementation.在指针返回后对指针的任何访问仍然不是线程安全的,但在您的实现中也不是访问。

Do you think this is a reliable implementation?你认为这是一个可靠的实现吗?

That depends on class T .这取决于 class T Some classes must be singleton because there can be only one instance at any given moment, physically.某些类必须是 singleton,因为在任何给定时刻,物理上只能有一个实例。 Ie an attempt to create a second instance would certainly fail, for example due to both of them requiring exclusive access to some unique external resource.即创建第二个实例的尝试肯定会失败,例如由于它们都需要对某些唯一外部资源的独占访问。

Proposed implementation does allow for concurrent construction of two instances of T , which may lead to wonderful race-induced bugs.提议的实现确实允许同时构造T的两个实例,这可能会导致奇妙的竞争引起的错误。

Edit: Even with the lock protecting new T , this solution still does not guarantee that T is constructed only once.编辑:即使有锁保护new T ,这个解决方案仍然不能保证T只构造一次。

Your implementation should only be used as an educational tool (use static in real software).您的实现只能用作教育工具(在实际软件中使用static )。
It has issues;它有问题; multiple objects can be created (and all but one are deleted again), but at least it is thread-safe.可以创建多个对象(除一个之外的所有对象都被再次删除),但至少它是线程安全的。

The first load can even be mo_relaxed since synchronization with compare_exchange(release) is covered by the load(mo_acquire) return statement.第一次load甚至可以是mo_relaxed ,因为与compare_exchange(release)的同步包含在load(mo_acquire) return 语句中。

In a DCLP implemention you would use a mutex to avoid creation of multiple objects and to block threads that are waiting for the creator to finish.在 DCLP 实现中,您将使用互斥锁来避免创建多个对象并阻止等待创建者完成的线程。 Since your implementation already allows multiple objects, the mutex is not necessary from a correctness point of view (unless indeed the constructor is not thread safe).由于您的实现已经允许多个对象,因此从正确性的角度来看, mutex不是必需的(除非构造函数确实不是线程安全的)。

If multiple threads create object T , the one that stores the pointer to _instance , releases the object (say thread N), while the others (say N+1) have to perform a load again;如果多个线程创建 object T ,存储指向_instance的指针的线程释放 object(例如线程 N),而其他线程(例如 N+1)必须再次执行load this second load(mo_acquire) in N+1 can never return nullptr . N+1 中的第二次load(mo_acquire)永远不会返回nullptr The compare_exchange in thread N+1 failed because it came later in the modification order than the first execution in thread N, which means that the compare_exchange (in N) also precedes the second load (in N+1) in the modification order and therefore it is guaranteed to return the object pointer to a synchronized object线程 N+1 中的compare_exchange失败,因为它在修改顺序中比线程 N 中的第一次执行晚,这意味着compare_exchange (在 N 中)也在修改顺序中的第二次加载(在 N+1 中)之前,因此保证将 object 指针返回到同步的 object

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM