![]() |
eXeL@B —› Программирование —› Синхронизация потоков |
Посл.ответ | Сообщение |
|
Создано: 14 мая 2007 18:43 · Поправил: Hellspawn · Личное сообщение · #1 Вот наконец освободился, решил курсач накодить. Вообщем задача такая, сихронизация потоков: - есть сервер к нему коннектятся клиенты, их два типа: - клиенты, которые читают инфу - клиенты, которые записывают инфу Ну и необходимо это всё закодить без косяков. Я сделал на потоках и сокетах. Т.е. коннектиться клиент, создаём поток, назначаем обработчики, ждём... Так или иначе нам надо либо отослать инфу из буфера, либо принять и записать в буфер. Надо защитить от стандартных ошибок. Терь вопрос, как лучше всего это реализовать (синхронизацию)? з.ы. мне больше всего приглянулись критические секции... ----- [nice coder and reverser] ![]() |
|
Создано: 14 мая 2007 19:11 · Личное сообщение · #2 |
|
Создано: 14 мая 2007 19:18 · Поправил: Hellspawn · Личное сообщение · #3 Bitfry пишет: ЗЫ Если я вообще правильно понял вопрос. ну несколько потоков будут постоянно вызывать процедуру - DoWork(const action:integer) в которой решается что собственно делать ![]() отказать клиенту, т.к. буфер переполнен или данных нет вообoе. Вот тут то и нужна синхронизация. з.ы. самое главное - сообщения не могут быть потеряны ![]() ----- [nice coder and reverser] ![]() |
|
Создано: 14 мая 2007 19:24 · Поправил: Icelot · Личное сообщение · #4 66.102.9.104/search?q=cache:qxT8J4tjpswJ:www.williamspublishing.com/PDF/5-8459-0879-5/content.pdf+%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F+%D0%B8%D0%BC%D0%B5%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D1%85+%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%BE%D0%B2&hl=ru&ct=clnk&cd=7&gl=ru не уверен, но вдруг поможет (главы 7-8) Там вверху указатель на пдф если я правильно понял. Ридер не стоит. ----- radio uno in ibisa ... ![]() |
|
Создано: 14 мая 2007 19:27 · Личное сообщение · #5 Hellspawn Критические секции подойдут вполне. Вообще нужно смотреть конкретно что за данные, как читаются, как пишутся и т.п. Рекомендую почитать Рихтера "Создание эффективных WIN32-приложений с учетом специфики 64-разрядной версии Windows" - там хорошо про синхронизацию написано. Книга есть в сети. ![]() |
|
Создано: 14 мая 2007 19:35 · Личное сообщение · #6 |
|
Создано: 14 мая 2007 20:02 · Личное сообщение · #7 amely пишет: бернуть операции работы с буфером в критические секции. пасиб, я так и думал что это самое то) тока не совсем понятно, как именно оборачивать... при старте проги: InitializeCriticalSection(CriticalSection); дальше, допустим так, поток N: ...
так норм? ... ----- [nice coder and reverser] ![]() |
|
Создано: 14 мая 2007 20:46 · Личное сообщение · #8 |
|
Создано: 14 мая 2007 21:34 · Личное сообщение · #9 |
|
Создано: 14 мая 2007 21:46 · Личное сообщение · #10 |
|
Создано: 15 мая 2007 01:09 · Личное сообщение · #11 Hellspawn, разбиваешь всё на несколько кусков: 1) протокол: например ASCII команды типа "write ID VALUE" типа "write USERS 1234" 2) клиент: на сокетах и win32 API: socket(), connect(), send() 3) сервер: GUI и один поток в котором всё крутится вокруг select(). Ему скармливаешь все сокеты, и потом обрабатываешь два типа событий: новое соединение (делаешь accept()) и RX на уже существующем (делаешь recv() и парсишь данные) Усё. Никаких там critical sections, events, wait for multiple objects.... P.S. Rascal не неси чепухи. Сначала напиши test case, воткни QueryPerformanceCounter() и померяй. ![]() |
|
Создано: 15 мая 2007 05:18 · Личное сообщение · #12 |
|
Создано: 15 мая 2007 05:36 · Личное сообщение · #13 asd пишет: Нафига вообще потоки придумали. Если рассуждать как ты, то любую прогу можно однопоточной сделать. Потоки реально нужны в нескольких случаях: - когда можно что-то распаралелить и получить повышенную скорость при наличии нескольких ядер - упростить структуру софта в ситуации когда софтина может скажем, обрабатывать много запросов очень быстро, и паралельно медленно что-нить записывать на диск. Ессно всё что угодно можно написать с одним потоком, таймерами и очередями, я это не предлагаю. Но, в случае простого сервера который, скажем, позволяет читать что-то из мелкой DB потоки не нужны - они всё равно будут ждать доступа к этой DB где будут locks. А использовать потоки "потому что они есть, и это круто" - это маразм. Думать надо, и смотреть - есть ли от этого польза. ![]() |
|
Создано: 15 мая 2007 06:27 · Личное сообщение · #14 |
|
Создано: 15 мая 2007 08:52 · Поправил: s0larian · Личное сообщение · #15 |
|
Создано: 15 мая 2007 09:36 · Личное сообщение · #16 |
|
Создано: 15 мая 2007 10:20 · Личное сообщение · #17 |
|
Создано: 15 мая 2007 13:33 · Личное сообщение · #18 Hellspawn, вот схожая ветка, может пригодится что... http://exelab.ru/f/action=vthread&forum=6&topic=7759 ----- Я медленно снимаю с неё UPX... *FF_User* ![]() |
|
Создано: 15 мая 2007 16:12 · Личное сообщение · #19 Hellspawn пишет: при старте проги: InitializeCriticalSection(CriticalSection); дальше, допустим так, поток N: ... EnterCriticalSection(CriticalSection); try If (action = BUF_READ) then s:=ReadBuf(); If (action = BUF_WRITE) then WriteBuf(s); finally LeaveCriticalSection(CriticalSection) end; так норм? нормально, но еще добавить DeleteCriticalSection при выходе из проги ![]() PS: примитивов синхронихации потоков есть большое множество, но имхо самый простой способ в данном случае - это критические секции. ![]() |
|
Создано: 15 мая 2007 16:39 · Поправил: Hellspawn · Личное сообщение · #20 |
|
Создано: 15 мая 2007 17:21 · Личное сообщение · #21 s0larian на сколько я помню сокеты есть синхронные и асинхронные. синхронные - поток останавливается до, например, получения данных recv. Интерфейс, на сколько я понимаю, не работает по понятным причинам. На счёт секций Rascal пишет: Крит секции говорят медленные Не я говорю. Кто то говорил. Я не тестил. Это было сказано больше для подтверждения или опровержения. Поэтому слова "не неси чепухи" я считаю неуместными ----- Недостаточно только получить знания:надо найти им приложение ![]() |
|
Создано: 15 мая 2007 20:07 · Личное сообщение · #22 asd, ты о пять не о том. Я привёл пример, который, как мне кажется, близок к тому что пишет Hellspawn. В моём примере, если писать имеено так как я упомянул, всё выльется в то что только один поток обращается к данным (к базе) в любой момент времяни. То есть, все потоки которые получают данные паралельно, всё равно превращаются в один из-за синхронизации. Так зачем тогда делать синхронизацию и потоки? Повторюсь, я не говорю что потоки вообще не нужны. Я говорю что если решение напоминает вышеописанный сценарий, то толку от потоков ноль, и есть потраченное время на реализацию и отладку. ![]() |
|
Создано: 15 мая 2007 21:40 · Личное сообщение · #23 s0larian пишет: всё выльется в то что только один поток обращается к данным (к базе) в любой момент времяни. То есть, все потоки которые получают данные паралельно, всё равно превращаются в один из-за синхронизации. Так зачем тогда делать синхронизацию и потоки? Для того, чтобы можно было параллельно обрабатывать/подготавливать полученные данные. По мне так это просто удобно. ![]() |
|
Создано: 15 мая 2007 22:07 · Личное сообщение · #24 asd пишет: s0larian пишет: всё выльется в то что только один поток обращается к данным (к базе) в любой момент времяни. То есть, все потоки которые получают данные паралельно, всё равно превращаются в один из-за синхронизации. Так зачем тогда делать синхронизацию и потоки? Для того, чтобы можно было параллельно обрабатывать/подготавливать полученные данные. По мне так это просто удобно. I rest my case ![]() ![]() |
|
Создано: 15 мая 2007 22:46 · Поправил: tnt17 · Личное сообщение · #25 Hellspawn пишет: - клиенты, которые читают инфу - клиенты, которые записывают инфу тебе еще это нужно учитывать, т.е. походу чтение-запись ведется паралелльно. Ситуация: Пусть процесс чтение занимает 1 условный такт, запись - 4 такта. t1: Процесс 1 хочет записать информацию(запись стартует не моментально) t2: Процесс 2 хочет прочесть информацию.Запись не завершена (осталось 3 такта); t3: Чтение, остался 1 такт; Запись еще 2 такта. t4: Чтение завершено;Запись - остался 1 такт t5: Запись завершена. Вот что нужно обмозговать: 1) как в момент когда производиться запись,процессу запросившему чтение вернуть старое значение буфера до окончания процесса записи.Тут именно учитывается продолжительность передачи всей последовательности данных по каналу связи(сеть например) 2) каким образом все это дело синхронизовать. Можно например создать 2 буффера: 1 на чтение,2 на запись.На них вешаешь 2 семафора(или что там у тебя). Подумай над переносом инфы из одного буффера во второй, там впринципе не сложно, но синхронизировать нужно. так что - думай ;) ----- – Почему ты работаешь по ночам ? – Так удобнее... В одну смену с чертями... ![]() |
|
Создано: 16 мая 2007 03:39 · Поправил: s0larian · Личное сообщение · #26 Hellspawn пишет: Вообщем задача такая, сихронизация потоков: - есть сервер к нему коннектятся клиенты, их два типа: - клиенты, которые читают инфу - клиенты, которые записывают инфу Так енто, как ты хранишь данные? А данные они для каждого клиента свои или все клиенты читают/пишут что-то общее? В первом случае вообще не надо locks, т.к. у каждого клиента свои данные (если для каждого клиента поток) Во втором, концептуально, тоже очень просто. Скажем, у тебя есть две функции:
Если сервер однопоточный, то locks не надо. Если многопоточный, то вставляешь в обе функции lock() и в конце unlock(). На windows реализовать этот lock() легко через CriticalSection. ![]() |
![]() |
eXeL@B —› Программирование —› Синхронизация потоков |