|
|
Регистрация Восстановить пароль |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
|
Опции темы | Поиск в этой теме |
26.03.2010, 23:56 | #1 |
Пользователь
Регистрация: 22.02.2010
Сообщений: 24
|
синхронизация потоков
Здравствуйте, уважаемые форумчане!
Нужно мне написать прогу на синхронизацию. Задача такая: есть поток, пишущий в канал по-байтно (вернее по целому числу), и три потока, читающие из канала. Читатели ждут, пока писатель не записал в канал очередной байт. После этого они считывают байт (обязательно все должны считать), а потом ждут пока будет записан следующий байт и т.д. Думал я сделать все на событиях. При этом одно событие с ручным сбросом связывается с писателем, и по одному событию с автосбросом с каждым читателем. Все потоки находятся в бесконечном цикле. Читатели в начале цикла ждут, пока писатель не запишет очередной байт. Писатель записывает байт и вызывает PulseEvent(), чтобы освободить все ожидающие потоки и сразу же снова сбросить событие. Если использовать для этого SetEvent()-ResetEvent(), то в промежутке между их вызовами некоторые читатели могут несколько раз считать байт. Если для писателя использовать событие с автосбросом, то оно освободит только одного читателя, а нужно всех. Затем писатель начинает ждать ВСЕХ читателей. Все получается здорово при одном читателе, а вот при нескольких - лажа: не все читатели успевают сработать, и возникает взаимная блокировка. Подскажите, пожалуйста, что в моей архитектуре не верно? Как нужно сделать правильно? Текст приложения: #include <stdio.h> #include <windows.h> #include <process.h> #define THREADS_NUM 3 //число читателей #define N 30 //предел //потоковая функция читателя DWORD WINAPI HostFunc(void*); //потоковая функция писателя DWORD WINAPI ChanelFunc(LPVOID); HANDLE HostEv[THREADS_NUM]; //события читателей HANDLE ChanelEv; //событие писателя DWORD temp = 0; //записываемая-читаемая величина struct { HANDLE hHost; } Hosts[THREADS_NUM]; //потоки-читатели HANDLE chanel; //поток-писатель int main(int argc, char argv[]) { //создаем события for(int i = 0; i < THREADS_NUM; i++) { HostEv[i] = CreateEvent(NULL, FALSE, FALSE, NULL); } ChanelEv = CreateEvent(NULL, TRUE, FALSE, NULL); for(int i = 0; i < THREADS_NUM; i++) { //запускаем читающие потоки Hosts[i].hHost = (HANDLE)_beginthreadex(NULL, 0, (unsigned int (__stdcall*)(void*))(HostFunc), (void*)i, 0, NULL); //запускаем поток-писатель chanel = (HANDLE)_beginthreadex(NULL, 0, (unsigned int (__stdcall*)(void*))ChanelFunc, NULL, 0, NULL); } getchar(); return 0; } DWORD WINAPI HostFunc(void* i) { while(temp != N) { WaitForSingleObject(ChanelEv, INFINITE); //ждем записи printf("thread#%i-%i ", (int)(i), temp); //просто выводим на консоль считанную величину SetEvent(HostEv[(int)i]); //сигнализируем писателю } return 0; } DWORD WINAPI ChanelFunc(LPVOID n) { while(temp != N) { temp++; printf("\nchanel: %i ", temp); //выводим на консоль записываемуюую величину PulseEvent(ChanelEv); //сигнализируем читателям WaitForMultipleObjects(THREADS_NUM, HostEv, TRUE, INFINITE); //ожидаем ВСЕХ читателей } return 0; } |
Похожие темы | ||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Синхронизация | kostyan142 | Общие вопросы по Java, Java SE, Kotlin | 6 | 13.01.2010 01:39 |
Синхронизация потоков с использованием именованых каналов | _Денис | Помощь студентам | 0 | 09.01.2010 16:58 |
Синхронизация | yarilo | Софт | 2 | 07.08.2009 15:50 |
Синхронизация колонок | eImage | Microsoft Office Excel | 4 | 13.03.2009 20:42 |