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

Thread safety when storing pointers to object in container

本文关键字:指针 线程 安全 对象 存储      更新时间:2023-10-16

我有一个关于需要实现互斥锁时的良好代码实践的问题。请考虑下面的代码示例,其中有一个管理器类 (Group(,它保存指向对象 (Person( 的指针容器。

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

因为当我执行"getPerson(("时,我会检索指针。但是当我尝试执行"getName(("时,可能已经删除/删除了 person 对象。这是如何以好的方式完成的?

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

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();
}

当我执行"getPerson(("时,我检索指针。但是当我尝试执行"getName(("时,可能已经删除/删除了 person 对象。

"已删除"部分听起来像是std::shared_ptr(https://en.cppreference.com/w/cpp/memory/shared_ptr(的一个很好的用例

如果在任何地方都使用共享指针,则永远不会显式删除对象:允许 shared_ptr 类在销毁或重新分配最后一个引用时(且仅在(自动删除它。

这并不能解决一个线程通过特定组中的成员身份获取对某人的引用,而另一个线程同时从同一组中删除同一个人意味着什么的问题。这是一个更高级别的争用条件,您可能只能通过实现一些适当的高级和特定于应用程序的策略来防止或应对。