![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| KaraKum |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 640 Регистрация: 3.12.2007 Репутация: 1 Всего: 1 |
Доброе время суток.
В коде:
возникает deadlock, думаю, по следующим причинам: выполнение останавливается после 1.1 (где size = 0) в потоке Reader и переключается на поток Writer где добавляется index в buffer (2.1) и оповещается bufferHasSome (2.2) (но никто этого оповещение ещё не ожидает и, поэтому, это пустая операция); затем процессор переключается назад на поток Reader (на 1.2) и начинает ждать пока кто-нибудь не заполнит buffer, но единственный кто его может заполнить - ожидает пока его кто-нибудь не освободит. Программа замораживается (возникает deadlock) примерно после 150 итераций - думаю именно по этому причине. Но если boost::mutex mutex; вынести в глобальное пространство, то deadlock уже больше не возникает (прогонял 200000 итераций) - почему? Это сообщение отредактировал(а) KaraKum - 20.2.2011, 01:23 |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
KaraKum
Честно говоря весь код не смотрел, но function-scope mutex привлек мое внимание, как абсолютно бессмысленная вещь. У каждой функции и у каждого потока будет свой mutex, который естественно не будет ничего защищать. Возможно оттого и проблема. Чтобы защищать какие-то общие данные для нескольких потоков, mutex должен быть общим для этих потоков, в этом весь его смысл. Один поток блокирует mutex, остальные ждут, пока тот разблокирует. Это сообщение отредактировал(а) azesmcar - 20.2.2011, 12:40 |
|||
|
||||
| KaraKum |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 640 Регистрация: 3.12.2007 Репутация: 1 Всего: 1 |
Это не "защищающий" мьютекс, или как он был назван. Локальные мьютексы созданы для того чтобы можно было создать boost::mutex::scoped_lock, который, в свою очередь, нужен для того чтобы создать boost::condition. То есть локальные мьютексы не используются для lock/unlock. В том-то и дело что если вынести эти мьютексы (то есть объединить) в глобальное пространство, то deadlock уже не возникает (хотя должен оставаться, ибо структура кода не меняется).
|
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
А зачем это нужно? тебе нужно ожидать с помощю фиктивного мьютекса? зачем это вообще? у тебя что-то не так с принципами. Ты используешь вещи не так, как они рассчитаны быть использованы. К тому же для reader/writer в boost вообще-то есть boost::shared_mutex. |
|||
|
||||
| KaraKum |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 640 Регистрация: 3.12.2007 Репутация: 1 Всего: 1 |
Принципы тут ни причём. Код надо было смотреть - boost::condition-то ведь используется одна. Я разобрался в этом. deadlock-а не было только потому scoped_lock создавался в самом начале потока и, следовательно, это было (становилось) вовсе не многопоточное приложение при глобальном мьютексе - потоки выполнялись по-очерёдно.
И, кстати, для каждого boost::condition нужно создавать свой собственный мьютекс - как в примере |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
еще как причем. читать многопоточный код с кучей goto - увольте В этом и есть смысл мьютекса. А у тебя на каждый поток по одному мьютексу, вот притом и принципы, что мьютекс в таких ситуация вообще не нужен, он тут не к месту.
да, только не нужно создавать по одному на каждый поток. Если тебе нужно сделать так, чтобы лишь бы как-то работало, то так и пиши. То, что ты пытаешься делать с помощью нескольких разных мьютексов, автоматически делает condition_variable с помощью одного, глобального. Это сообщение отредактировал(а) azesmcar - 21.2.2011, 10:17 |
|||
|
||||
| KaraKum |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 640 Регистрация: 3.12.2007 Репутация: 1 Всего: 1 |
Смысл мьютекса не только в этом, а ещё в том чтобы замораживать потоки и обеспечивать выгрузку кэша процессора. То есть ты угадал на 33%. Для boost::condition именно так и нужно - по одному мьютексу на boost::condition.
Так изначально и работало - вопрос и стоял в форме "почему работает?", хотя должен был возникать deadlock.
Вопрос был про реализацию потоков от буста, а не в решении какой-то задачи. Код портировал из реализации потоков на WinAPI, но ничего подногобно boost::mutex::lock и boost::condition не видел ни в WinAPI, ни в posix threads. Узналось что деструктор boost::mutex::lock освобождает мьютекс да и boost::condition.notify_one(), при этом, становится блокированным. Безосновательная полемика, но пока формируется петиция на форум, то как-то лучше понимается своя же задача - теперь реализация буста более-менее понятна |
||||
|
|||||
| azesmcar |
|
||||||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
вообще-то мьютекс не занимается выгрузкой кэша, он по требованию к блокирующему обьекту упорядочивает память. Хотя я не вижу где тебе здесь нужны барьеры, но в любом случае ставить барьер мьютексом, это как убивать тараканов водородной бомбой и это не имеет ничего общего с предназначением мьютекса. Можно и термосом забить гвоздь, но это не значит, что термосы для этого создавались.
На boost::condition а не на поток, это совершенно разные вещи.
У тебя что, цель сделать программу не рабочей? В конечном итоге ты пишешь программу, которая должна работать, или я чего-то не понимаю? ты про lock_guard? Это обычный RAII wrapper. lock (читай EnterCriticalSection) в конструкторе и unlock (читай LeaveCriticalSection) в деструкторе. Да пожалуйста http://msdn.microsoft.com/en-us/library/ms...2(v=vs.85).aspx
Там велосипедов нет. Все есть и на WinAPI и в POSIX. Добавлено через 10 минут и 54 секунды вообще алгоритм работы condition-а довольно прост. ему передается заблокированный мьютекс, когда condition помещается в ожидание, он разблокирует мьютекс и начнет спать до тех пор, пока его не разбудит какой нибудь notify_one или notify_all. Далее, он просыпается и снова блокирует мьютекс. Т.е. когда он не спит - мьютекс заблокирован и можно обращаться к общим данным. Это сообщение отредактировал(а) azesmcar - 22.2.2011, 15:13 |
||||||||
|
|||||||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |