考虑这个类:
#include <vector>
class A {
private:
std::vector<int> m_vector;
public:
void insertElement(int i) {
m_vector.push_back(i);
}
const std::vector<int>& getVectorRef() const {
return m_vector;
}
};
该方法
getVectorRef
线程安全吗?
是否有可能在
getVectorRef
返回期间另一个线程弹出并调用 insertElement
,从而导致成员向量发生更改并且 getVectorRef
的调用者获得错误的 const 引用?
两个 const 限定符(一个用于向量,另一个用于成员函数)在线程安全上下文中没有意义吗?
成员函数是线程安全的,但你的接口不是。在设计为线程安全的类中,您不能对您维护的对象产生references,就好像用户将引用保留在周围,她可以在其他操作到位时使用它。
成员函数在技术上是线程安全的。对成员的引用基本上是它的地址,并且该地址不能更改。无论其他线程在做什么,该引用将始终引用完全相同的对象。但这通常不是您主要关心的问题。真正关心的是用户可以用函数的返回来做什么,在这种情况下,答案基本上是无事。
一旦用户获得引用,通过它进行的任何访问在与原始对象中该成员的任何修改相结合时都将导致竞争条件。一旦放弃引用,就无法提供安全同步,无法从产生引用的类中创建线程安全接口。
如果您需要使访问线程安全,您可以选择复制值(在关键部分内)或提供更细粒度的函数来处理来自用户的更高级别的请求。
我推荐 Anthony Williams 的 C++ concurrency in action 来进行一些关于如何使接口线程安全的讨论。