Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Синхронизация потоков Mutex 
V
    Опции темы
Migelь
Дата 5.3.2009, 00:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 25.2.2009

Репутация: нет
Всего: нет



Доброго времени суток!
Рассказываю о моей "беде".
Главный поток программы создает вторичный поток, в который передает указатель на глобальную переменную типа myTime. 
Поток вычисляет количество секунд пошедших от начала суток до указанного времени и выводит на экран. Затем запоминает время и в последующем вычисляет разницу между новым и старым значениями. Так продолжается до тех пор, пока не будет передано время 00:00:00, после этого поток завершается. 
Главный поток в цикле вводит с клавиатуры значение времени во временную переменную time, необходимо синхронизировать потоки для корректной работы программы с помощью: критическая секция, Mutex, событие, семафоры. Я выбрал Mutex как самый простой и наиболее подходящий, на мой взгляд, для такого случая . Завершение цикла – ввод значения 00:00:00.
=====
Теперь о главном - что не фурычит. С потоками происходят непонятные вещи: то не подключается ThreadFunction, а то и наоборот подключается и выполняет несколько раз свой цикл. Mutex по идее и должен от таких "сюрпризов" уберечь, однако так не происходит, в чем может быть ошибка?

=====
Код

#include <windows.h>
#include <iostream.h>
#include "myTime.h"

myTime time;
HANDLE hThread;
HANDLE hMutex;

DWORD WINAPI ThreadFunction(LPVOID);

int main()
{
    cout<<"privet"<<endl;
    DWORD threadid;    
    hThread = CreateThread(NULL,0,ThreadFunction,&time,CREATE_SUSPENDED,&threadid);
    SetThreadPriority(hThread,THREAD_PRIORITY_ABOVE_NORMAL);
    hMutex=CreateMutex(NULL,FALSE,NULL);
    ResumeThread(hThread);
    do
    {
        WaitForSingleObject(hMutex,INFINITE);
        GetTime(&time);
        ReleaseMutex(hMutex);
    }while(Proverka(time));
    CloseHandle(hThread);
    CloseHandle(hMutex);
    return 0 ;
}

DWORD WINAPI ThreadFunction(LPVOID lpParam)
{
myTime zero={0,0,0};
    do
    {
        WaitForSingleObject(hMutex,INFINITE);
        PutTime(time);
        PutTime(zero);
        cout<<"Raznost - "<<DiffTime(time,zero)<<endl;
        zero=time;
        ReleaseMutex(hMutex);
    }while(Proverka(time));
    return 0;
}


На всякий случай еще source и header файлы проги, если вдруг кто решит "собрать".
Код

#include <windows.h>
#include <iostream.h>
#include "myTime.h"

#define LIBEXPORT __declspec(dllexport)

LIBEXPORT void GetTime(myTime* t)
{
    cout<<"GetTime"<<endl;
    cout<<"Vvedite vremia: chas, minuti, sekundi"<<endl;
    cin>>t->h>>t->m>>t->s;
    if ((t->h > 23)||(t->h < 0))
    {
        cout<<"vvedite zanovo vremia - vvedeno nekorrektno"<<endl;
        GetTime(t);
    }
    if ((t->m > 59)||(t->m < 0))
    {
        cout<<"vvedite zanovo vremia - vvedeno nekorrektno"<<endl;
        GetTime(t);
    }
    if ((t->s > 59)||(t->s < 0))
    {
        cout<<"vvedite zanovo vremia - vvedeno nekorrektno"<<endl;
        GetTime(t);
    }
}

LIBEXPORT void PutTime(myTime t)
{
    cout<<"PutTime"<<endl;
    cout<<t.h<<" "<<t.m<<" "<<t.s<<endl;
}

LIBEXPORT void AddTime(myTime* t1,myTime t2)
{
    cout<<"AddTime"<<endl;    
    t1->s+=t2.s;
    if (t1->s > 59)
    {
        t1->s-=60;
        t1->m+=1;
    }
    t1->m+=t2.m;
    if (t1->m > 59)
    {
        t1->m-=60;
        t1->h+=1;
    }
    t1->h+=t2.h;
    if (t1->h > 23)
    {
        t1->h-=24;
    }
}

LIBEXPORT int DiffTime(myTime t1,myTime t2)
{
    cout<<"DiffTime"<<endl;
    int s=0;
    s=t1.s-t2.s;
    s+=60*(t1.m-t2.m);
    s+=3600*(t1.h-t2.h);
    return s;
}

LIBEXPORT bool Proverka(myTime time)
{
    if ((time.h==0)&(time.m==0)&(time.s==0))
    {
        return 0;
    }
    else 
    {
        return 1;
    }
}

======
Код

#ifndef  IMPORTLIB
    #define IMPORTLIB __declspec(dllimport)
#endif

IMPORTLIB struct myTime
{
    unsigned h;    
    unsigned m;    
    unsigned s;    
};

IMPORTLIB void GetTime(myTime*);
IMPORTLIB void PutTime(myTime);
IMPORTLIB void AddTime(myTime*,myTime);
IMPORTLIB int DiffTime(myTime,myTime); 
IMPORTLIB bool Proverka(myTime);


Вот такие пироги.

PM MAIL   Вверх
Migelь
Дата 5.3.2009, 00:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 25.2.2009

Репутация: нет
Всего: нет



Я тут нашел, кое-что 
http://forum.vingrad.ru/forum/topic-186295...utex/index.html
Правда, мне это не сильно помогло. Пробовал ставить sleep после ReleaseMutex(hMutex); - никакой разницы, за исключением задержки, те же чудеса.
PM MAIL   Вверх
Sirt
Дата 5.3.2009, 04:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 3.3.2009

Репутация: нет
Всего: нет



Mutex уберегает вас только от того, что секции, ограниченные WaitForSingleObject и ReleaseMutex, будут выполняться как единый блок относительно друг друга. То есть, например, GetTime никогда не выполнится между PutTime(time) и PutTime(zero) в вашем случае. Однако, очередность захвата Mutex-а никто не гарантирует, в частности, совершенно нормально, что дополнительный поток или основной могут захватить его пару раз подряд. Если нужно строго последовательное выполнение блоков в основной программе и дополнительном потоке, то это нужно обеспечивать самостоятельно. Первое, что пришло в голову - глобальная переменная, проверяемая на истинность и устанавливаемая в ложность внутри критической секции в одном потоке и наоборот - в другом.
PM   Вверх
Lazin
Дата 5.3.2009, 06:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 27
Всего: 154



не нужно устанавливать приоритет потоку, это раз
ф-я Proverka, проверяет значение общей переменной, но при этом, поток уже не владеет мютексом, поэтому, ф-я может быть вызвана во время изменения переменной time, два smile 
PM MAIL Skype GTalk   Вверх
Migelь
Дата 5.3.2009, 10:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 25.2.2009

Репутация: нет
Всего: нет



Убрал приоритет потока, что помогла не только от огромного зацикливания, иногда проскакивавшего, но и, что меня удивило, дало результатом то, что управление стало гарантированно передаваться от первого потока ко второму. Далее я просто поставил Sleep(50) сразу после ReleaseMutex(hMutex) в ThreadFunction и, вроде бы, все стало работать корректно. Все, всем спасибо за помощь. smile 
PM MAIL   Вверх
xvr
Дата 5.3.2009, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Корректно он все равно не работает - одного Mutex'а недостаточно. Сюда еще напрашивается семафор для сигнализации о новом значении time
Да и Lazin по поводу некорректного вызова Proverka тоже абсолютно прав.

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0459 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.