Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 26.03.2010, 23:56   #1
m_kostik
Пользователь
 
Регистрация: 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;
}
m_kostik вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Синхронизация 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