假设我有一个看起来像这样的类(实际上正是这个大小):
class K
{
public:
long long get_x() const; // lock m_mutex in shared/read-only mode
void update( long long w ); // lock m_mutex with a unique_lock
private:
long long m_a;
long long m_b;
long long m_c;
long long m_x;
double m_flow_factor;
mutable boost::shared_mutex m_mutex;
};
如您所见,这应该是线程安全的。更新函数一次被一个线程调用,未知但只有一个线程(保证),但访问器可以同时被多个线程调用。
update 函数正在更改所有值并且被调用得非常频繁(每秒一百次)。正如您猜到的那样,当前的实现会锁定很多。
我正在考虑使用 std::atomic 来避免锁定并可能使此代码更高效。但是,我确实需要更新函数来一起更新值。 因此,我正在考虑做这样的事情:
class K
{
public:
long long get_x() const
{ return data.load().x; }
void update( long long w )
{
auto data_now = data.load();
// ... work with data_now
data.store( data_now );
}
private:
struct Data {
long long a;
long long b;
long long c;
long long x;
double flow_factor;
};
std::atomic<Data> data;
};
我目前对 std::atomic 的理解是,即使这段代码比之前的代码更具可读性(因为它没有到处都有锁声明),因为 K::Data 结构是“大", std::atomic 将只用普通的互斥锁实现(所以无论如何它都不应该比我最初的实现更快)。
我说的对吗?
最佳答案
任何对 std:atomic 的特殊化都将涉及内部锁定,因此您一无所获,现在您还面临着以前没有的加载和存储之间的数据竞争,就像这样在以前的版本中对整个 block 进行了独占锁定(我想?)。
此外,对于 shared_mutex,使用普通互斥锁与 shared_mutex 进行分析可能是明智的,您可能会发现普通互斥锁的性能更好(这一切都取决于您持有锁的时间)。
shared_mutex 的好处只有在长时间持有锁以进行读取并且写入很少时才能看到,否则 shared_mutex 中涉及的开销会扼杀您对普通互斥锁的任何 yield 。
关于c++ - 共享互斥量是否比相对较大结构的原子更有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14008799/