gpt4 book ai didi

c++ - 以下单例实现线程安全吗?

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:01:11 24 4
gpt4 key购买 nike

下面的单例实现线程安全吗?::Instance 方法应该是正确的,Dispose 是我自己创建的,所以要确保我没有遗漏任何东西。

std::atomic<S *> S::_instance;
std::mutex S::_singleton_mutex;

S& S::Instance()
{
using namespace std;
S * tmp = _instance.load(memory_order_relaxed);
atomic_thread_fence(memory_order_acquire);
if (tmp == nullptr)
{
lock_guard<mutex> l(_singleton_mutex);
tmp = _instance.load(memory_order_relaxed);
if (tmp == nullptr)
{
tmp = new S();
atomic_thread_fence(memory_order_release);
_instance.store(tmp, memory_order_relaxed);
}
return *tmp;
}

void S::Dispose()
{
using namespace std;
S * tmp = _instance.load(memory_order_relaxed);
atomic_thread_fence(memory_order_acquire);
if (tmp != nullptr)
{
lock_guard<mutex> l(_singleton_mutex);
tmp = _instance.load(memory_order_relaxed);
if (tmp != nullptr)
{
atomic_thread_fence(memory_order_release);
_instance.store(nullptr, memory_order_relaxed);
delete tmp;
}
}
}

最佳答案

解决方案是:是的,看起来不错。

更多信息:

当您可以接受在短时间内可能拥有两个实例时,第二个实例将立即被销毁,您可以摆脱互斥体:

std::atomic<S *> S::_instance;

S& S::Instance()
{
using namespace std;
auto tmp = _instance.load(memory_order_relaxed);
if (tmp == nullptr)
{
auto tmp2 = new S();
if( !_instance.compare_exchange_strong(tmp, tmp2) )
delete tmp2;
}
return *tmp;
}

void S::Dispose()
{
using namespace std;
auto tmp = _instance.load(memory_order_relaxed);
if (tmp != nullptr)
{
if( _instance.compare_exchange_strong(tmp, nullptr) )
delete tmp;
}
}

当两个线程同时启动 Instance() 时,都看到一个 nullptr 并创建一个新的 S。其中只有一个会成功替换实例指针,而另一个会立即删除新的 S。

无论如何,您可能更喜欢使用 Scott Meyers 单例,尽管它没有提供处理对象的方法:

S& S::Instance() 
{
// This instance will be created at first call - thread safe.
// it lives until the program terminates.
static Singleton instance;
return instance;
}

顺便说一句,这是最优雅、最少的代码和线程安全的。

关于c++ - 以下单例实现线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33627326/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com