![]() |
|
Модераторы: xvr |
![]()
|
|
| Perovskit |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 30.7.2008 Репутация: нет Всего: нет |
Добрый день
Я немного запутался в потоках. Пожалуйста, развейте сомнения. Имеем класс: class X { private: //... bool valid; public: void Close(); bool IsValid() { return valid; } }; void X::Close() { valid = false; } Имеется два потока. В первом есть такое: std::vector <X*> clients; И он крутится в цикле с таймаутом 200мс. А в другом -- работа с клиентами. Периодически вызываются разные функции. Но вот, какой-то клиент потерял смысл(не валидный): 2-й поток: clients[i]->Close(); На каждой итерации первый поток ищет невалидных клиентов и удаляет их: for(;;) { delay(200); //... if(!clients[i].IsValid()) { delete clients[i]; удаляем указатель из вектора } } Вопрос: возможно ли, что сразу после выполнения valid = false во втором потоке управление передастся в первый поток, где IsValid == false и будет вызвано delete clients[i] в то время, когда второй поток так и не вышел из функции-члена этого класса? Получится так, что первый поток удалил класс, хотя в нем еще находился второй поток. Это верно? И как с этим бороться (если надо)? |
|||
|
||||
| Alexeis |
|
|||
![]() Амеба Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: нет Всего: 459 |
Вполне возможно, но в этом нет ничего страшного. Функция класса почти ничем не отличается от простой функции. Важно чтобы после выполнения valid = false; не производилось обращение к другим полям объекта. А так ничем не грозит. -------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
|||
|
||||
| Perovskit |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 30.7.2008 Репутация: нет Всего: нет |
все ясно. Благодарю.
|
|||
|
||||
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 1 Всего: 154 |
нужно синхронизировать доступ к вектору, если другие потоки читают из вектора, то из него ничего нельзя удалять, и наоборот, если один из потоков удаляет элементы из вектора, ни один другой поток не должен иметь возможность читать из него данные, так как может произойти reallok буфера вектора и у другого потока окажется невалидный итератор...
самый простой вариант - использовать мьютекс... перед тем как обратиться к данным вектора поток должен его захватить, а после этого - освободить, более оптимальным будет использование Read-Write блокировок (в случае если несколько потоков могут одновременно, безопасно читать данные, это соблюдается для STL контейнеров, но может не соблюдаться для твоих классов)... еще более оптимальным было-бы использование более удобных для многопоточной обработки структур данных, которые можно изменять из разных потоков одновременно.. зы используй тэги [code] |
|||
|
||||
| Alexeis |
|
|||
![]() Амеба Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: нет Всего: 459 |
Lazin, это уже другой вопрос. Читай внимательно
То что поток находиться в функции объекта никак не мешает его удалению, если в функции нет обращений к полям класса. То что обращение к общим данным требует синхронизации очевидно, я говорил о том что завершение функции объекта не приводит к обращению к его полям. -------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
|||
|
||||
| Perovskit |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 30.7.2008 Репутация: нет Всего: нет |
Lazin все верно, но все экземпляры класса X конструктором регистрируются в отдельном статическом векторе и обслуживаются вторым потоком. По сути, код первого и второго потоков совершенно независим. Там-то естественно мьютексами защищаются данные от одновременного доступа и когда класс теряет смысл, он безопасно удаляется из статического вектора и поднимается флажок valid = false. Да, это не очень приятно, т.к. вообще говоря, корректность зависит от явного положения valid=false именно в конце ритуала по невалидности клиента.
Можно в деструктор клиента засунуть захват мьютекса, но пока не понял, где его еще захватить чтобы гарантировать, что после удаления не будет обращений к внутренним членам класса. |
|||
|
||||
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 1 Всего: 154 |
так и есть Добавлено через 3 минуты и 55 секунд может использовать подсчет ссылок? например boost::shared_ptr, в этом случае объект будет удален только после того как программа не может к нему обратиться (так как ссылок на него больше нет) в этом случае нужно будет просто удалить объект из контейнера... |
|||
|
||||
| Perovskit |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 30.7.2008 Репутация: нет Всего: нет |
Да, не подумал.
Хорошая идея, спасибо. |
|||
|
||||
![]()
|
| Правила форума "С/С++: Программирование под Unix/Linux" | |
|
|
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, xvr. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Программирование под Unix/Linux | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |