我试图让my_class
线程安全如此。
class my_class
{
const std::vector<double>&
get_data() const
{ //lock so that cannot get_data() while setting data
lock l(m_mutex);
return m_data;
}
void
run()
{
vector<double> tmp;
//some calculations on tmp.
{ //lock so that cannot get_data() while setting m_data
lock l(m_mutex);
m_data = tmp; //set the data
}
}
private:
std::vector<double> m_data;
mutex m_mutex;
my_class(); //non-copyable
}
run()
和get_data()
可能由不同的openmp
线程调用,因此我引入了一个锁。
(因为我使用openmp,m_mutex
和lock
是围绕omp_init_lock();
等命令的RAII包装器。
但是,get_data ()
上的锁定对于创建和销毁是很昂贵的(当我分析我的代码时,这是最昂贵的操作 - 我经常调用get_data()
)。
是否可以重新组织my_class以移除get_data()
中的锁定?或者这种锁定是不可避免的并行代码成本?
答案 0 :(得分:3)
第一步是研究读写锁:这样多个读者就不会相互阻塞。
下一步是使用无锁或无等待操作。网上有很多资源比我能够更好地描述它们。只需注意一点:无锁方法处理原子(互锁)操作,这意味着数据大小需要很小。如果你走这条路,你将原子地替换一个指向你的向量的指针,而不是整个向量。这意味着你的类会变得更复杂,并会处理一些指针和内存管理。
答案 1 :(得分:0)
在get_data / run函数周围使用关键部分可能更便宜,不会产生额外的设置/拆除开销(因为关键部分是静态初始化的),但这也会同步该类的其他实例。