![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| xTr1m |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 692 Регистрация: 9.2.2005 Где: Москва Репутация: 1 Всего: 1 |
День добрый, есть такая задача. Я запускаю один поток, который заполняет некий список. Также я запускаю несколько потоков (функция-обработчик у них одна), которые из этого списка значения тягают. Самой простой вариант этих двух функций выглядит как-то так
Но, как я понимаю, тут есть проблема (может и не одна), которая заключается в том, что потоки, которые "обрабатывают" значения из главного списка, работают постоянно. То есть бесконечный цикл, постоянно проверяет кол-во элементов на > 0. А ведь это процессорное время и т.п. Тогда я подумал сделать какое-нибудь событие. Типа поток, который AddToList, добавляет в список элемент и сигнализирует, "мол в списке что-то появилось, давайте, обрабатывайте". Но тогда в каком месте нужно ставить событие в состояние "список пуст, больше брать нельзя". Что мне приходит на ум: 1. добавить это в функцию GetFromToList, но ведь это просто обработчик, зачем ему проверять пуст ли список и создавать какое-то событие, к тому же его тоже нужно блокировать мьютексом, что не было одновременно можно-нельзя. 2. можно завести еще один поток, который бы синхронизировал этот момент. Но это тоже какой-то огород получается. 3. может есть другое решение? Спасибо. |
|||
|
||||
| cppGhost |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 101 Регистрация: 24.4.2013 Репутация: нет Всего: нет |
Мммм, то ли я плохо сформулировал вопрос, то ли это большой секрет =))
Переформулирую на каком-нибудь примере: на сервер поступают запросы (это первый поток). на сервере запущено несколько потоков, которые обрабатывают, поступившие запросы. Список запросов представляет собой вектор. Как мне кажется, неправильно делать так, чтобы эти потоки раз в N-секунд смотрели не пуст ли вектор запросов. Нужно этим потокам как то сообщать, что вектор уже не пуст. И так же нужно как то сообщать им, что запросы все обработаны и нужно подождать. Ну как то так. У меня не такая задача. У меня задача понять, как это грамотно реализуют. |
|||
|
||||
| xvr |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 60 Всего: 223 |
Грамотно это реализуют применением примитивов синхронизации, например семафором и/или событий. Например семафор (который со счетчиком) считает количество элеменов в списке. При помещении в список семафор увеличивают на 1, при попытке чтения - ждут на нем. Если в списке есть элементы - ожидание завершается и счетчик автоматически уменьшается. Если же элементов нет, то поток чтения блокируется, пока элементы не появятся |
|||
|
||||
| xTr1m |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 692 Регистрация: 9.2.2005 Где: Москва Репутация: 1 Всего: 1 |
Почитал еще литературу на эту тему и нашел то, что нужно в новом стандарте. Выглядит примерно так:
то есть в потоке, который считывает значения будет захвачен мьютекс, проверен результат IsListEmpty, если true то функция GetFromList пойдет дальше. Если false, то мьютекс освобождается и дальше идет ожидание вызова notify_one() как сигнала к еще одной проверке. Понятно, что гуру и так все знали =)) , но расписал я тут, чтобы самому еще раз это осмыслить, да и может кому то пригодится. xvr, за идею тоже спасибо, но с событиями наверное будет лучше. А может нет, тогда просьба рассказать почему?) |
|||
|
||||
| akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Надо смотреть, как работают при многопоточности контейнеры стандартной библиотеки.
Что-то такое читал, что то ли в стандарте контейнеры не safe-threaded, а в Intel Threading Blocks проблема решена. Но надо уточнять. -------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
STL контейнеры не реализуют потокобезопасность.
|
|||
|
||||
| akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Я ставил tbb месяца 4 назад чтоли, мне надо было под винду портировать одну из замороченных библиотек на основе компьютерного зрения. Там использовался этот tbb и в нем как-то потокобезопасность для элементарных контейнеров, кажется, была реализована (интеловская кроссплатформенная библиотека для потоков). Так, на всякий случай информация Это сообщение отредактировал(а) akizelokro - 10.10.2013, 16:11 -------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
| akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Вообще, по теме самого вопроса, более правильно, думаю, если не использовать потокобезопасную версию с этим tbb, то желательно бы "делать остановку" (mutex, auto, семафор, критическую секцию) полностью
для всего логического фрагмента. Потому что в общем случае контейнер может от момента определения числа элементов в векторе до момента вставки изменяться сколь угодно произвольно. А остальное, кажется, по идее должно быть правильным. Если использовать потокобезопасную версию tbb, то там нужно вспоминать, как такие вещи реализуются. Если интересна загрузка различных потоков с различными приоритетами выполнения, то это, по-моему, тоже делается. Это сообщение отредактировал(а) akizelokro - 10.10.2013, 16:37 -------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
akizelokro, в спецификации STL указано, что контейнеры потокобезопасны для чтения, но для записи нет. То, что кто-то сделал их безопасные версии, я не сомневаюсь. Но когда ты используешь что-то нестандартное, то ты знаешь зачем и что это дает.
|
|||
|
||||
| akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Энто, конечно, да.
Тут даже если пофлудить немного ненавязчиво захочется, много не попишешь. Поэтому внушает Это сообщение отредактировал(а) akizelokro - 11.10.2013, 07:26 -------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
| xvr |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 60 Всего: 223 |
Рассмотрим такой сценарий -
Не будет. Пример: Конфигурация потоков -
Сценарий исполнения -
|
|||
|
||||
| xTr1m |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 692 Регистрация: 9.2.2005 Где: Москва Репутация: 1 Всего: 1 |
xvr, пример я брал из книги. попробовать это на компе пока не было времени, но что я понял из описания. В строке 28 захватывается мьютекс, в строке 29 проверяется возвращаемое значение CThreadsDlg::IsListEmpty. Если оно false, то мьютекс освобождается, а сам поток ожидает вызова notify_one для m_condition и deadlock'а вроде быть не должно.
так тут смысл в том, чтобы поток записи пишет сам по себе, независимо от потоков чтения. ждать их он не должен. Это сообщение отредактировал(а) xTr1m - 11.10.2013, 19:27 |
|||
|
||||
| xvr |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 60 Всего: 223 |
Не должен != не будет. В описанных мною сценариях вы получите делок всей системы. Даже если ваш поток записи ничего не ждет, вы можете потерять неопределенное количество элементов из очереди (они до потока чтения не дойдут) Это еще не гарантия того, что он рабочий Ошибки в синхронизации потоков очень коварны, они могут не проявится за много часов работы (у разработчика), и сломаться немедленно у пользователя вашей программы.
Ага, да, в ожидание conditional variable mutex попадает. Тогда Deadlock'а по первому сценарию не будет, но по второму остается (либо dedlock либо потеря данных) |
|||
|
||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |