76 / 50 / 26
Регистрация: 22.02.2015
Сообщений: 306
|
||||||||||||||||
1 | ||||||||||||||||
Безопасное использование вектора в двух потоках30.03.2016, 19:00. Показов 939. Ответов 4
Метки нет (Все метки)
Это продолжение этой темы , но уже немного другая проблема.
Работаю с классом , который создаёт объекты через shared_ptr и заносит их в std::vector. В двух потоках: 1 проверяет время жизни объекта, 2 рисует. Проблемы две и серьёзные, бывает что кидают исключени и это связано с векторами: 1) Иногда кидает искл. на Obj_Bullet::getPos(); 2) Иногда в циклах thread#1 и thread#2 бывают ошибки типа: (нельзя инкрементировать вектор), но это когда создаётся слишком много объектов и быстро. Ниже сокращённые исходники. Что я не правильно делаю ? Core.h - класс управления объектами Thread#1 - поток 1 Thread#2 - поток 2 core.h
thread#1
thread#2
0
|
30.03.2016, 19:00 | |
Ответы с готовыми решениями:
4
ArrayList. Безопасное использование в потоках Использование одной переменной в двух потоках Использование одного вектора вместо двух Безопасное использование итератора С++ |
11 / 15 / 8
Регистрация: 12.10.2011
Сообщений: 802
|
|
30.03.2016, 19:51 | 2 |
Посмотри блокировки, мьюмиксы и тд... книга многопоточное программирование.
0
|
В астрале
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
|
|
30.03.2016, 20:22 | 3 |
DUMP, Учитывая, что могут часто происходить erase, лучше бы использовать список/дек, ибо там удаление быстрое.
Ну и локать нужно на удалении. Да и на доступе вообщем-то тоже.
0
|
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
|
|
30.03.2016, 21:43 | 4 |
Расширенная версия:
DUMP, Есть пара вопросов для выбора алгоритма, сколько вы памяти готовы пожертвовать?(на самом деле там копейки, но все же) И насколько вы ленивы? 1) Как и было сказано - лочить каждый объект отдельно при доступе. При использовании листа можно будет и контейнер изменять(добавлять/удалять элементы) 2) Завести по своему вектору на каждый тред. И если процесс удаления инициируется только из одного треда, то синхронизировать векторы вот так : Завести третий вектор "удаленных элементов" в который кладутся удаленные элементы во время процесса удаления в логическом потоке. Поток рендера, перед/после основного цикла отрисовки, синхронизирует свой вектор, удаляя из него элементы перечисленные в векторе удаленных элементов. Таким образом мы избавляемся от блокировки при чтении, и блокируем только третий вектор во время удаления(логический поток)/синхронизации(поток рендера). + : Блокировки очень короткие, и также их мало, если в векторах можно изменять последовательность элементов(сортировка не важна) то все очень быстро будет работать. - : Покодить придется, ибо это только удаление, а нам еще добавлять элементы надо. Возможна рассинхронизация на "кадр" между отрисовкой и логикой(т.е. добавленный объект отрисуется лишь через кадр, хотя мог бы и в этом кадре, либо же проживет еще лишний кадр при удалении) но это не столь заметно( да и можно полечить это). Ну и чуть лишней памяти, но это мелочи. 3) Вы не ленивы, и у вас есть память, тогда: Также как и 2-ой вариант, но вектор "удаленных элементов" представлен двумя векторами, которые блокируются только для того чтобы свапнуться. Один вектор обрабатывается в одном треде, другой в другом. Свап происходит в начале или конце основного цикла обработки. + : Блокировок в общем-то нет, можно даже свап сделать lockfree. - : В случае элементарной логики свапа векторов "удаленных элементов", мы получим практически неопределенное поведение, но опять же это можно поправить, но тогда никакого lockfree, хотя может быть вы адский задрот Если мы хотим удалять/добавлять элементы в обоих потоках: То можно сделать так : Свап происходит в конце основного цикла обработки. В начале цикла вектор содержит элементы которые были удалены в другом потоке, в конце цикла элементы которые были удалены в этом потоке. Но это наложит ограничение в синхронизации по кадрам, хотя и добавит определенности и стабильности при синхронизации. А можно накинуть еще "свапающиеся вектора" и избавиться от синхронизации по кадрам. В общем, удачи
1
|
76 / 50 / 26
Регистрация: 22.02.2015
Сообщений: 306
|
|
31.03.2016, 13:34 [ТС] | 5 |
eagl69, мьюмиксы ? Мьютексы не подойдут.
Nosey, Интересный вариант с двумя векторами и третим промежуточным, но может быть большая рассинхронизация т.к. мне нужно пробежаться по вектору удалённых объектов и для каждого удалённого найти его в основном векторе второго потока( что рисует и не может удалять объекты ). К тому же нужно сделать временную блокировку. А вот третий способ в точности как второй , но два вектора удалённых объекта ? И можно сделать Lockfree , но тогда у меня при добавление/удалении объектов итератор может выдать иключение. Но если фиксить это локами, то какая выгода по сравнении со вторым способом ? Мб я не понял вовсе, но идеи мне нравятся. Спасибо.
0
|
31.03.2016, 13:34 | |
31.03.2016, 13:34 | |
Помогаю со студенческими работами здесь
5
Обработка вектора в разных потоках Безопасное использование строки подключения Безопасное использование API веб-сайта Использование флагов в потоках Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |