在容器中存储指向对象的指针时的线程安全性

时间:2019-06-17 14:55:58

标签: c++ pointers thread-safety containers

当需要实现互斥时,我有一个关于良好代码实践的问题。考虑下面的代码示例,其中有一个管理器类(组),其中包含一个指向对象(人)的指针的容器。

如果Group类由多个线程共享,那么访问Person对象的公共方法的正确方法是什么?

因为当我执行'getPerson()'时,我检索了指针。但是,当我尝试执行'getName()'时,有可能已删除/删除了人员对象。如何做到这一点的好方法?

编辑:此示例不是多线程的,但请考虑在多线程环境中使用的此类:)

class Person 
{
public:
    Person(std::string name, std::string place) :
    m_name(name),
    m_place(place) {};

    ~Person() {};

    std::string getName(){return m_name;}
    std::string getPlace(){return m_place;}

private:
    std::string m_name;
    std::string m_place;
};

class Group
{
public:
    Group() :
    m_persons(100) {};

    ~Group(){};

    void createPerson() {
        std::lock_guard<std::mutex> l(m_mtx);
        Person* p = new Person("John", "London");
        m_persons.push_back(p);
    }

    void removePerson(int index) {
        std::lock_guard<std::mutex> l(m_mtx);
        m_persons.erase(m_persons.begin() + index);
    }

    Person* getPerson(int index) {
        std::lock_guard<std::mutex> l(m_mtx);
        return m_persons[index];
    }

private:
    std::vector<Person*> m_persons;
    std::mutex m_mtx;

};

int main() {
   Group g();
   g.createPerson();
   g.createPerson();

   std::cout << g.getPerson(0).getName();
}

1 个答案:

答案 0 :(得分:0)

  

当我执行'getPerson()'时,我检索了指针。但是,当我尝试执行'getName()'时,有可能已删除/删除了人员对象。

“已删除”部分听起来像是std::shared_ptrhttps://en.cppreference.com/w/cpp/memory/shared_ptr)的一个好用例

如果在各处使用共享指针,则永远不会显式删除对象:您允许shared_ptr类在(且仅在)最后一个引用被破坏或重新分配时自动删除它。

这不能解决以下问题:一个线程通过其在特定组中的成员身份获得对某人的引用,而另一个线程同时将该人从同一组中删除。这是一个更高级别的竞争条件,您可能只能通过实施一些适当的高层且 application-specific 策略来预防或应对。