| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Программирование под Unix/Linux > Параллельное выполнение потоков |
| Автор: mephis 7.5.2012, 01:34 | ||||
Здравствуйте. нужно написать программу, которая лезет в БД, проверяет значения в ячейках и запускает таймер (время = значение ячейки) в отдельном потоке. потоки должны выполняться параллельно.
в таком варианте потоки запускаются и отрабатывают по очереди. если закоментить pthread_join, то таймеры не запускаются. как решить проблему? |
| Автор: boostcoder 7.5.2012, 10:26 |
| убери pthread_join() и используй барьер. Добавлено через 45 секунд после while() |
| Автор: xvr 7.5.2012, 11:41 |
| Передавать в pthread_create this в качестве параметра для создаваемого thread'а - плохая идейя. У вас все thread'ы передерутся за этот this, т.к. нет никакой гарантии, что Deamon::threadFunction прочтет данные оттуда раньше, чем цикл while в Deamon::connectDB их перезапишет для следующего потока. Во вторых - надеюсь, что вызов threadDmn->curTimer.at(threadDmn->number).startTimer(); блокируется, иначе у вас все запущенные потоки немедленно завершаться, до наступления заданного timeout'а (а если так и задумывалось, то зачем вообще нужны потоки?) |
| Автор: mephis 7.5.2012, 20:51 | ||
можно подробнее объяснить, как это нужно делать? |
| Автор: boostcoder 7.5.2012, 21:05 |
| гуглить: pthread_barrier_init() pthread_barrier_wait() pthread_barrier_destroy() |
| Автор: mephis 8.5.2012, 09:36 | ||
переделал программу, используя барьеры. в дебаг режиме всё работает как часы, а вот в обычном - проблема. как уже заметил товарищ xvr, у меня number инкрементируется раньше, чем заканчивает выполнение pthread_create, поэтому в последней итерации я выхожу за пределы массива myThread и ловлю сегфолт. посоветуйте, пожалуйста, как эту проблему решить. |
| Автор: boostcoder 8.5.2012, 13:22 |
| для начала, pthread_barrier_wait() перемести в Deamon::connectDB() после цикла. |
| Автор: mephis 8.5.2012, 13:35 | ||
когда я перемещаю его под while(), таймеры вообще не запускаются. извиняюсь за криворукость, не туда вставлял. работает. |
| Автор: boostcoder 8.5.2012, 13:47 |
ошибка с number тоже пропала? |
| Автор: mephis 8.5.2012, 13:52 | ||||
нет. как я понимаю, пока выполняется pthread_create, происходит инкремент number и в функцию попадает уже увеличенное на 1 значение . я обошел это таким способом:
но я опасаюсь, что на менее/более быстрых процессорах это всё полетит к чертям и будет путаница. поэтому хочу найти нормальное решение проблемы. |
| Автор: boostcoder 8.5.2012, 14:45 |
| что-то не въезжаю... твой код расщитан на пять потоков. т.е. ты уверен что в БД всегда пять записей? |
| Автор: mephis 8.5.2012, 16:15 | ||
нет, там могут быть от 1 до 5 записей. |
| Автор: boostcoder 8.5.2012, 16:55 |
| т.е. не больше пяти? никогда? Добавлено через 4 минуты и 21 секунду а number тебе в какие моменты инкрементировать нужно? |
| Автор: mephis 8.5.2012, 17:01 | ||||
честно говоря, в базе может быть сколько угодно записей и на каждую запись требуется таймер. но пока я делаю фиксированную длину. поэтому сейчас да - не больше 5. Добавлено через 50 секунд
number инкрементировать нужно после того, как отработал pthread_create. |
| Автор: boostcoder 8.5.2012, 17:15 |
сейчас оно так и есть. не понимаю, в чем проблема? |
| Автор: mephis 8.5.2012, 17:24 | ||
да, оно так и есть. проблема в том, что, когда использую number в threadFunction, он уже приходит не со своим значением, а number+1. то есть получается у меня так, что number каким-то образом инкрементируется раньше, чем нужно и в threadFunction он уже попадает инкрементированным. поэтому на первой итерации у меня стартует не 0-й таймер, а 1-й. на последней итерации получаю сегфолт, т.к. number на 1 выше, чем моё количество таймеров. |
| Автор: boostcoder 8.5.2012, 17:32 |
| тогда тебе нужно не - а - тогда когда запустилась функция потока. и почему number не инкрементировать в функции потока? |
| Автор: mephis 8.5.2012, 17:37 | ||
пробовал раньше, до исправления с барьером, ничего не менялось. приду с работы, попробую сделать так ещё раз. |
| Автор: boostcoder 8.5.2012, 17:39 |
| в функцию потока передай указатель на number. в ней, разыменовываешь его, и инкрементируешь. |
| Автор: sergioK1 8.5.2012, 22:43 | ||
вот тут
может быть что счетик увеличиваеться до вызова threadFunction, может быть и нет, но это решает OS програмист на это повлиять не может, boostcoder барьер тут не поможет, с передачай указателя да , cчетчик должен быть внутри threadFunction - это просто логичнее, поговорка есть на такой случай , "При правильном дизайне программа пишеться сама " |
| Автор: xvr 10.5.2012, 14:13 | ||
Вынесите number из Deamon вообще, и передавайте его отдельной структурой (вместе с this) на куче:
Тогда барьеры не нужны |
| Автор: mephis 11.5.2012, 11:04 | ||||
так и сделал. всё работает. всем спасибо за помощь. |
| Автор: xvr 11.5.2012, 11:15 |
Кстати, если у вас это не учебная задача, и критично быстродействие при запуске thread'ов, то у этого подхода есть маленький недостаток. На каждое создание thread'а будет вызванна пара new/delete. Этого можно избежать заранее выделив массив из структур Data и передавая в создаваемый thread указатели на элементы этого массива по очереди (только надо внимательно следить за индексом элемента, что бы он не вышел за границы массива и не наложился на все еще используемые элементы) |
| Автор: mephis 13.5.2012, 13:26 | ||
задача не учебная. и если будут присутствовать 1000 и больше thread-ов, то проблемы быстродействия сразу скажутся. программа должна работать в реальном времени с постоянно меняющимися данными в БД, поэтому каждое промедление будет критично и может привести к сбою. благодарю за замечание, я это обязательно учту. |
| Автор: sergioK1 13.5.2012, 13:45 | ||
1000 средов на одной машине ? так может подумать о threadPool |