const方法返回const引用的线程安全性

5

考虑以下这个类:

#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限定符(一个为向量,另一个为方法)在上下文中没有任何意义吗?


2
“线程安全”这个词有时被过度使用,听起来像是一种魔法弹药,你只需要将其应用于某段代码中,就能轻松实现并发编程。是的,“getVectorRef”是“线程安全”的,但这个信息有什么用呢?你仍然可以通过给定的接口创建大量错误的代码。你仍然需要理解你的代码在做什么! - Kerrek SB
1
你需要确保在线程之间同步访问向量,请参阅https://dev59.com/1W855IYBdhLWcg3wbztl以获取更多信息。 - HeatfanJohn
1个回答

4
该成员函数是“线程安全”的,但您的接口并不安全。在一个被设计为线程安全的类中,您不能返回对维护对象的引用,因为如果用户保留了该引用,她可以在其他操作正在进行时使用它。
从技术上讲,该成员函数是线程安全的。对成员的引用基本上是其地址,而该地址不会改变。无论其他线程正在做什么,该引用始终将指向完全相同的对象。但这通常不是您的主要关注点。真正的问题是用户可以通过函数的返回值做什么,在这种情况下,答案基本上是“什么也不能做”。
一旦用户获得引用,任何通过它的访问都将在与原始对象中该成员的任何修改相结合时导致竞态条件。一旦您放弃了引用,就无法提供安全同步,没有办法从产生引用的类中创建线程安全的接口。
如果需要使访问线程安全,则可以选择复制该值(在临界区内)或提供更精细的函数来处理用户的更高级请求。
我建议阅读Anthony Williams的《C++ concurrency in action》以了解如何使接口线程安全的一些讨论。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接