Безопасность потока при хранении указателей на объект в контейнере - PullRequest
0 голосов
/ 17 июня 2019

У меня есть вопрос о хорошей практике кода, когда мьютекс должен быть реализован.Рассмотрим следующий пример кода, где есть класс менеджера (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();
}

1 Ответ

0 голосов
/ 17 июня 2019

когда я выполняю getPerson (), я получаю указатель. Но когда я пытаюсь выполнить getName (), возможно, объект person уже удален / удален.

«Уже удаленная» часть звучит как хороший пример использования для std::shared_ptr (https://en.cppreference.com/w/cpp/memory/shared_ptr)

Если вы используете общие указатели повсеместно, то вы никогда не удаляете объект явно: вы разрешаете классу shared_ptr автоматически удалять его, когда (и только когда) последняя ссылка уничтожена или переназначена.

Это не решает проблему того, что означает, что один поток получает ссылку на человека через членство в определенной группе, в то время как другой поток одновременно удаляет этого человека из той же группы. Это состояние гонки более высокого уровня, которое вы, вероятно, можете предотвратить или справиться только с помощью реализации соответствующей политики высокого уровня и для конкретного приложения .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...