Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Синхронизация процессов


Автор: Lazin 7.1.2010, 16:26
мне нужно записывать данные в большое количество файлов, асинхронно, причем несколько приложений могут писать данные в один и тот-же файл, я использую IOCP для организации неблокирующего I/O
что-бы не испортить данные, каждое приложение, перед тем, как записать что-либо, ждет именованное событие, после того, как запись окончена, приложение снова устанавливает это событие в signaled state
теперь собственно проблема
если один из потоков, входящих в пулл потоков, пытается что-либо записать в файл, при этом файл занят другим процессом, то этот поток блокируется, но в идеале, в обработчиках асинхронных событий не должно быть блокирующих операций вообще, иначе пулл потоков может уйти в режим ожидания и новые события некому будет обрабатывать

Я понял, что события/мьютексы мне не очень подходят, возможно я смогу переделать свой алгоритм так, что-бы состояние примитива синхронизации проверялось, но ожидания не происходило...

Существует ли какой-либо механизм синхронизации процессов, основный на обмене сообщениями между процессами?

Добавлено через 6 минут и 28 секунд
попробую уточнить, запись происходит так
- синхронизация процессов (блокирует поток на некоторое время)
- начало записи
...
- вызов обработчика окончания записи (освобождает файл, устанавливая событие)

между последним и первым пунктами, проходит достаточно много времени, все это время, поток другого процесса может быть заблокирован

Автор: jonie 7.1.2010, 19:03
Цитата


Существует ли какой-либо механизм синхронизации процессов, основный на обмене сообщениями между процессами?
готового наверняка нет...ну, разве что на ум приходит MPI и подобное (это из раздела распределенные вычисления)...

Автор: fry 8.1.2010, 04:06
Если я правильно понял, то:
Думаю алгоритм можно реализовать ....

если будет иметь место "связывание" файла (или некоторого их множества) с определенным потоком выполнения, при этом коллизии исключаются по определению, 

или 

если поток может отложить выполнение записи и "заняться" чем-нибудь другим.

Первый вариант на мой взгляд может быть интересен. Его реализация позволит исключить блокировку, при этом необходимо обеспечить сортировку заданий для потоков перед их выполнением. Правда возможен дисбаланс по нагрузке для потоков, но при небольшой доработке думаю можно и это компенсировать. Сразу скажу, сам так еще не делал, просто написал что первое в голову пришло.  smile 

Второй вариант вроде смахивает на классическое решение, но как я понял он тут не применим.

Цитата

разве что на ум приходит MPI и подобное (это из раздела распределенные вычисления)...

Дело-то не в распараллеливании вычислений, а в синхронизации обработки без необходимости блокировки. В принципе, если пользоваться технологиями распределенных вычислений, то поддерживающая их система (MPI, PVM или еще что) скорее всего не реализует эту функциональность (просто смысл у нее другой) и как бы затраты на ее работу(передача по сети или межпроцессное взаимодействие) не свели все "плюсы" на нет в отношении производительности.

Цитата

Существует ли какой-либо механизм синхронизации процессов, основный на обмене сообщениями между процессами?

Думаю не совру если скажу, что сделать можно все, а вот имеет ли смысл пользоваться тем, что сделал вопрос.
Можно, например, создать систему передачи маркера, где каждый маркер будет представлять определенный файл и синхронизировать операции его касающиеся. При этом каждый процесс будет знать можно ли ему выполнять некоторое задание без необходимости блокировки или нет.

Автор: ksili 8.1.2010, 08:34
Цитата(Lazin @  7.1.2010,  20:26 Найти цитируемый пост)
Существует ли какой-либо механизм синхронизации процессов, основный на обмене сообщениями между процессами?

А может сделать так?
В один файл пишет только один процесс, а все другие, скидывают ему сообщением WM_COPYDATA то, что надо им записать в тот же файл. Сообщения будут приходить в очередь по-любому по-очереди smile так что данные испортиться не должны. Но не надо в OnCopyData() сразу писать в файл, иначе будут задержки и та же блокировка (WM_COPYDATA вроде шлётся только через SendMessage, т.к. возвращает ответ отправителю). Надо помещать данные в буфер и по-быстренькому отвечать отправителю, чтобы он продолжал работать, а вывод в файл сделать в другом потоке того же процесса.

Может быть такое решение позволит вообще писать во все файлы из одного процесса, а все остальные будут скидывать ему в WM_COPYDATA ещё инфу о том, в какой именно файл писать.

Я сам так не делал, только сейчас придумал.

Автор: Lazin 8.1.2010, 11:00
Цитата(fry @  8.1.2010,  04:06 Найти цитируемый пост)
если будет иметь место "связывание" файла (или некоторого их множества) с определенным потоком выполнения, при этом коллизии исключаются по определению, 
связывание с потоком невозможно, так как у меня есть несколько процессов, в одном процессе коллизий и так не происходит

Цитата(ksili @  8.1.2010,  08:34 Найти цитируемый пост)
В один файл пишет только один процесс, а все другие, скидывают ему сообщением WM_COPYDATA то, что надо им записать в тот же файл. 

это будет крайне неэффективно, синхронная обработка сообщений тут не будет работать, я использую неблокирующий/асинхронный IO по одной простой причине - нужно обрабатывать очень много информации, обычно у меня идет запись на скорости - близкой к максимальной скорости записи жесткого диска

реализовал так:
определяю что и куда нужно писать, далее вызываю WaitForSingleObject, с нулевым таймаутом. Если ресурс(файл) захвачен, то начинаю асинхронную запись в файл, иначе, вызываю PostQueuedCompletionStatus и передаю туда нужные параметры, далее, один из потоков(из пулла потоков) получит соответствующий пакет завершения и попытается повторить запись, в случае неудачи он опять ее(запись) отложит и тд
Это работает отлично.

Автор: Dem_max 12.1.2010, 15:30
вот собственно почитай рихтера  (там в конце синхронизация потоков)  http://wm-help.net/books-online/book/59464/59464.html

Автор: Lazin 12.1.2010, 15:51
Dem_max, 
во первых, я какбэ в курсе
во вторых, синхронизировать потоки не нужно, мне нужно синхронизировать асинхронные вызовы процедур, происходящие в разных процессах
в третьих, я уже нашел решение и написал об этом
кажется я начинаю подозревать, что ты не читал топик прежде чем всех просветить

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)