![]() |
|
|
![]()
|
|
| JanryMayers |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 71 Регистрация: 11.6.2009 Где: Украина, г. Киев Репутация: нет Всего: нет |
Здрастье всем!
При решении определённой задачи возник, вопрос необходимо ли использовать mutex, если да то можете объяснить как будет работать программа с ним и без него? Задача: Основной поток запускает x вспомогательных, бесконечно добавляющих в некий контейнер свой элемент, потоков с некоторой изменяющейся задержкой. При этом он удаляет самый старый элемент в случае, если тот был добавлен другим потоком или если количество элементов в контейнере >Y (вот эта часть условия не ясна до конца). вот кусок кода
подскажите что нужно добавить в метод run? Это сообщение отредактировал(а) JanryMayers - 24.1.2011, 01:38 |
|||
|
||||
| borisbn |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 48 Всего: 135 |
А где же ?
Для синхронизации между потоками в твоём случае я бы передавал в потоки не просто указатель на list, а на класс-наследник от list, который бы включал в себя ещё 2 метода - lock и unlock, а также private-член mutex. Тогда run() выглядел бы след.образом
Ну, а что должны делать ф-ции lock/unlock - думаю понятно. И ещё. Правильнее было бы написать конструктор так:
Ну, и раз уж пошла такая пьянка ... Я бы передавал не указатель, а ссылку на list -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
||||||
|
|||||||
| JanryMayers |
|
||||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 71 Регистрация: 11.6.2009 Где: Украина, г. Киев Репутация: нет Всего: нет |
Спасибо, borisbn. Добавил бы те в репутацию, но постов малавата).
То есть получается mutex должен быть один единственный на все потоки. А какое у него должно быть начальное значение? И на счет функций lock/unlock:
я правильно мысль уловил? ...
почему? объясни, приведи пример) у мя щас выглядит так
и ещё варнинг warning C4355: 'this' : used in base member initializer list на m_thread( new boost::thread(boost::bind(&mThread::run, this)) ); Это сообщение отредактировал(а) JanryMayers - 24.1.2011, 11:58 |
||||||
|
|||||||
| azesmcar |
|
||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 3 Всего: 211 |
да. какое есть. конструктор по умолчанию все сделает. нет, классы scoped_lock, unique_lock, shared_lock... и так далее нужны для безопасности исключений. В частности scoped_lock заблокирует мьютекс в конструкторе и разблокирует в деструкторе, т.е.
эффект этой функции - 0! и еще..надо стараться блокировать как можно меньший участок кода. В частности, если код выглядет вот так то смысл использования потоков мне не совсем понятен, все равно все выполняется последовательно. Добавлено через 1 минуту и 51 секунду да, и тема тут не совсем в правильном разделе, попрошу ка я модераторов перенести ее в "Общие Вопросы". |
||||
|
|||||
| borisbn |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 48 Всего: 135 |
просто мне ссылки больше нравятся. Ты не сможешь передать нулевой указатель (ссылки на 0 не бывает) и тебе, соответственно, не нужно всё время проверять if ( ptr != 0 ) { ptr-> ...
полностью на 100% согласен. просто в коде, представленном ТС, по другому никак. Плюс его программа, скорее всего, либо для обучения потокам и мьютексам, либо она гораздо больше и сложнее, а в том коде lock'ать необходимо, т.к. там front(), size(), pop_front() и push_back() идут непосредственно др.за др.
если это - и вся программа, то да, никакого смысла. посмотри у boost::mutex должны быть ф-ции типа lock/unlock. и ещё, в данном конкретном случае модификатор mutable IMHO бессмысленный, тем более, что ф-ции твоего класса Case не константные -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
||||||
|
|||||||
| JanryMayers |
|
||||||||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 71 Регистрация: 11.6.2009 Где: Украина, г. Киев Репутация: нет Всего: нет |
теперь правильно?
задача у мя такая.
тогда лучше в этом куске кода каждое обращение к Case обработать mutex'ом
если у мя пустой список как я могу от него взять первый элемент?!! Это сообщение отредактировал(а) JanryMayers - 24.1.2011, 16:30 |
||||||||||
|
|||||||||||
| borisbn |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 48 Всего: 135 |
ага
у тебя и так идёт обращение в каждой строке:
-------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
||||
|
|||||
| JanryMayers |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 71 Регистрация: 11.6.2009 Где: Украина, г. Киев Репутация: нет Всего: нет |
все таки странное условие, если я его правильно понял то
контейнер будет всегда состоять из одного элемента? О_о а то и вообще пустой Это сообщение отредактировал(а) JanryMayers - 24.1.2011, 17:51 |
|||
|
||||
| borisbn |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 48 Всего: 135 |
задание то тебе ставили - тебе и разбираться
если у первого потока задержка 10 сек, а второго одна, и они кладут элементы "1" и "2" соответственно, то в контейнере будет много 2-ек и мало единиц ( или вообще единиц не будет) и ещё. почему у тебя добавление элемента по else от удаления? Насколько я понял должно быть ЕСЛИ НУЖНО УДАЛИТЬ { УДАЛИТЬ; } ДОБАВИТЬ; -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 3 Всего: 211 |
Мьютексом ничего не обрабатывается. Вкратце опишу работу мьютексов. Мьютекс - объект, имеющий минимум 2 функции - lock() и unlock(). Мьютекс может быть заблокирован одним потоком только один раз (есть и рекурсивные мьютексы, но это другой вопрос). Если мьютекс заблокирован одним потоком, то другой поток при попытке блокировке будет ждать, пока первый его не разблокирует. Таким образом мьютексы обеспечивают последовательность выполнения в параллельном мире. Т.е. часть своей функции ты можешь выполнить НЕ параллельно, а последовательно. Это значит, что эту часть кода (ту, что находиться между lock() и unlock() может выполнить одновременно лишь один поток. Следовательно, если вся функция находиться в критической секции, то и смысла использовать потоки нет, с тем же успехом эта функция может быть вызвана в цикле (вру, не с тем же, циклом будет оптимальнее). Надеюсь понятно описал. В принципе да, но 1. от std::list наследовать не стоит, он для этого не предназначен. 2. зачем нужны функции lock() и unlock()? класс (раз уж он потокобезопасен) сам должен понимать когда нужно блокировать мьютекс а когда разблокировать, от пользователя это должно быть скрыто. Это сообщение отредактировал(а) azesmcar - 24.1.2011, 22:37 |
|||
|
||||
| JanryMayers |
|
||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 71 Регистрация: 11.6.2009 Где: Украина, г. Киев Репутация: нет Всего: нет |
спасибо за описание
а что посоветуете вместо std::list?? или его просто использовать в объект класса Case
вот такой код вроде работает как нужно. Конфликтов вроде нет. только при вводе с клавиатуры при работе потоков, нужно немного ждать, что бы они завершились. Думаю в этом нет ничего страшного. Это сообщение отредактировал(а) JanryMayers - 25.1.2011, 03:28 |
||||
|
|||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 3 Всего: 211 |
Вместо list - ничего, list хорош, но вместо наследования могу посоветовать композицию. Вообще если браться за задачу правильно, то чтобы сделать лист потокобезопасным его нужно написать самому (можно и на основе стандартного, но попотеть придется). Тогда это позволит блокировать минимум кода, приведу пример. Список (std::list) - это структура, которая имеет ссылки на предыдущий и следующий элемент previous_node <-- node --> next_node каждая структура к тому же хранит значение. Сейчас, чтобы добавить элемент в список ты блокируешь весь список, выбора у тебя нет, хотя это тебе и не нужно. На самом деле, если ты добавляешь элемент в конец списка, другие потоки могут спокойно читать, удалять и добавлять в начало, но в случае полного блокирования этого не будет. Можно решить этот вопрос, если к примеру создавать мьютекс для каждого элемента (накладно, но и тут есть решение) и при работе с конкретным элементом блокировать только его, и его соседей. Это просто пример. если между lock и unlock выскочит исключение будет deadlock. Используй boost::scoped_lock. Это сообщение отредактировал(а) azesmcar - 25.1.2011, 08:03 |
|||
|
||||
| borisbn |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 48 Всего: 135 |
в данном случае у тебя вообще неправильно должно работать, т.к. локируешь ты ДО цикла, а разлокируешь ВНУТРИ. Т.е. если придерживаться этого варианта, а не того, что советует azesmcar (кстати - правильного, но более тяжеловесного), то должно быть как-то так
Это сообщение отредактировал(а) borisbn - 25.1.2011, 10:04 -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
||||
|
|||||
| JanryMayers |
|
||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 71 Регистрация: 11.6.2009 Где: Украина, г. Киев Репутация: нет Всего: нет |
её что нужно рендомить?... если да, то в каком диапозоне, лучше всего?
и что делать с этим this? он у мя варнинг сыпет warning C4355: 'this' : used in base member initializer list Это сообщение отредактировал(а) JanryMayers - 25.1.2011, 10:21 |
||||
|
|||||
| borisbn |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 48 Всего: 135 |
повторю что означает фраза в задании, которое тебе ставили - я не знаю по поводу warning'a - вообще-то от них необходимо избавляться, но в данном конкретном случае его (C4355) можно отключить, т.к. в стандарте сказано:
а boost::bind 100% не будет "refer to the object" being они initialized или не being -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
|||
|
||||
![]()
|
| Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets" | |
|
|
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |