gpt4 book ai didi

c++ - 在 C++11 - 多线程中,我们是否需要互斥锁来访问单例对象中的数据字段?

转载 作者:太空狗 更新时间:2023-10-29 20:24:39 24 4
gpt4 key购买 nike

据我了解,C++ 11 具有静态线程安全性。这意味着获取/创建单例的实例没有问题。这是因为静态现在是线程安全的,在多线程环境中不会造成任何问题。但是,问题是我是否需要一个互斥锁来访问单例中的数据字段。真的和单例有关吗?在多线程环境中访问数据字段时,即使模式不是单例,是否也需要互斥锁。这是完整的代码。

class Singleton
{
private:

Singleton()
{
std::cout<<"Singleton Initialized"<<std::endl;
}

Singleton(Singleton const&)
{
std::cout<<"Singleton copy constructor not allowed"<<std::endl;
}

Singleton& operator=(Singleton const&)
{
std::cout<<"Singleton Assignment Operator not allowed"<<std::endl;
}

~Singleton()
{
std::cout<<"Singleton Destructor not allowed"<<std::endl;
}

int m_data;

public:

int getData()
{
return m_data;
}

void setData(int data)
{
m_data = data;

}

static Singleton * instance( )
{
static Singleton *single_manager = new Singleton();
return single_manager;

}

};

最佳答案

tl;dr:是的。

C++ 11“静态线程安全”防止竞争条件:

static Singleton *single_manager = new Singleton();

没有它,可能的问题是:

  • Singleton() 实例化了两次
  • 不同的线程看到不同的单例实例
  • 单例初始化对其他线程不可见

但是,从不同线程调用时,对 m_data 的任何访问(即 GetDataSetData)都需要一个互斥量。


锁在哪里 - 单例应该在里面加锁,还是调用者应该加锁?
(根据评论)

这个问题没有简单的答案。

会向单例类添加锁并锁定 GetData/SetData。理由:几乎总​​是这是默认用例,可以减轻调用者的负担。

但是:
内锁并不总是足够的,例如如果你有:

Singleton * s = Singleton::instance();
int x = s->GetData();
x = x + 1;
s->SetData(x);

调用者需要在 Get/Modify/Set 周围使用外部锁。

反对内部锁的论点如下:

  • 在一般情况下,内部锁是不够的,即有些情况下调用者需要自己的锁
  • 当调用者无论如何都必须加锁时,内部锁会成为一个很重要的性能问题。

结论:如果您可以避免手头数据的 get-modify-set 场景,添加内部锁似乎是明智的(例如,API 可以包含 IncrementData) 方法。清楚地记录接口(interface)的线程安全性(例如,“此类不是线程安全的,需要外部锁定”“单个函数调用是线程安全的”)


注意事项:

是的:正如您已经想到的:这与类是单例无关。
如果数据真的只是一个 int,则可以使用“原子整数”(例如来自 boost:.atomic)。但是,获取/设置/修改问题仍然存在。

关于c++ - 在 C++11 - 多线程中,我们是否需要互斥锁来访问单例对象中的数据字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27035446/

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