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


Автор: iPlay 23.9.2007, 19:50
Значит писал я прогу с 2мя процессами и синхронизировал их спомощью мютексов. Теперь же хочу научится работать с потоками. Тоесть у меня текст тех процессов есть а хочу так чтобы они выполнянлись потоками, а потом добавить синхронизацию с помощью критических секций. Вот что я попробывал сделать:

Код

const char FileName[]="in.txt";

DWORD WINAPI Print_ThreadProc( LPVOID ) 

    char buf[80];
    FILE *file = fopen(FileName,"r");
      if (file == NULL){
        cout << "No such file";
        return 1;
      }
    fgets(buf,80,file);
    cout << buf << "\n";
    fclose(file);
    system("Pause");
    return 0; 
}; 

DWORD WINAPI Change_ThreadProc( LPVOID ) 
{
    char buf[80];
    char buf_out[] = "File has been modifyed";
    FILE *file = fopen(FileName,"w");
      if (file == NULL){
        cout << "No such file";
        return 1;
      }
    fputs(buf_out,file);
    fclose(file);
};

void main()
{
    DWORD dwPrint_ThreadId;
    DWORD dwChange_ThreadId;

    HANDLE hPrint_Thread = CreateThread(NULL, 0, Print_ThreadProc, 0, 0, &dwPrint_ThreadId);    
    HANDLE hChange_Thread = CreateThread(NULL, 0, Change_ThreadProc, 0, 0, &dwChange_ThreadId);    
    Sleep(3000);
}


Вот заработало у меня всё... но остался вопрос по поводу 4 параметра ф-ции  CreateThread, что он показывает?

Автор: JackYF 23.9.2007, 20:43
блииин... гуглом пользоваться умеешь?

MSDN (пошел по первой же ссылке)
Цитата

HANDLE WINAPI CreateThread(
  __in          LPSECURITY_ATTRIBUTES lpThreadAttributes,
  __in          SIZE_T dwStackSize,
  __in          LPTHREAD_START_ROUTINE lpStartAddress,
  __in          LPVOID lpParameter,
  __in          DWORD dwCreationFlags,
  __out         LPDWORD lpThreadId
);

Отсюда мы видим, что 4-й параметр имеет имя lpParameter. Его значение - при создании потока ты можешь ему передать 32-битное целое.

Автор: iPlay 23.9.2007, 20:52
Умею. Я просил объяснить почеловечески так как не понял что MSDN пишет.

Добавлено через 6 минут и 18 секунд
Подскажите как сделать синхронизацию с критической секцией тоесть чтобы сначало поток поменял значение файла а потом вывел уже смененные данные. Я попробывал вот так но всё равно сначало выводится потом меняется  smile 
Код

const char FileName[]="in.txt";

DWORD WINAPI Print_ThreadProc( LPVOID ) 

    CRITICAL_SECTION cls;
    InitializeCriticalSection(&cls);
    EnterCriticalSection(&cls);
    char buf[80];
    FILE *file = fopen(FileName,"r");
      if (file == NULL){
        cout << "No such file";
        return 1;
      }
    fgets(buf,80,file);
    cout << buf << "\n";
    fclose(file);
    system("Pause");
    LeaveCriticalSection(&cls);
    return 0; 
}; 

DWORD WINAPI Change_ThreadProc( LPVOID ) 
{
    CRITICAL_SECTION cls;
    InitializeCriticalSection(&cls);
    EnterCriticalSection(&cls);
    char buf[80];
    char buf_out[] = "File has been modifyed";
    FILE *file = fopen(FileName,"w");
      if (file == NULL){
        cout << "No such file";
        return 1;
      }
    fputs(buf_out,file);
    fclose(file);
    LeaveCriticalSection(&cls);
};

void main()
{
    DWORD dwPrint_ThreadId;
    DWORD dwChange_ThreadId;

    HANDLE hPrint_Thread = CreateThread(NULL, 0, Print_ThreadProc, 0, 0, &dwPrint_ThreadId);    
    HANDLE hChange_Thread = CreateThread(NULL, 0, Change_ThreadProc, 0, 0, &dwChange_ThreadId);    
    
    WaitForSingleObject(hChange_Thread, INFINITE);
    WaitForSingleObject(hPrint_Thread, INFINITE);
    
    CloseHandle(hPrint_Thread);
    CloseHandle(hChange_Thread);
    Sleep(3000);
}

Автор: Earnest 23.9.2007, 20:59
Что-то я не поняла: а где тут синхронизация и критические секции?

А насчет параметра - это любой параметр, который можно впихнуть в 32битное целое. Например, адрес структуры с твоими данными. Дальше этот параметр передается твоей функции потока и может там использоваться.


Автор: JackYF 23.9.2007, 21:02
Ты в этих двух потоках создал разные критические секции. А тебе нужно использовать одну и ту же.

вот это
Цитата(iPlay @  23.9.2007,  20:52 Найти цитируемый пост)
CRITICAL_SECTION cls;


убери из функций обеих потоков и напиши перед всеми функциями, как глобальную переменную.

Инициализацию критической секции вынеси в main(), она для каждой секции тоже должна вызывать только один раз.

Автор: iPlay 23.9.2007, 21:10
Earnest, ты второй код прочитай.


JackYF, создал но всё равно сначало выводит потом меняет.

Автор: zkv 23.9.2007, 21:21
Цитата(iPlay @  23.9.2007,  21:10 Найти цитируемый пост)
создал но всё равно сначало выводит потом меняет.

Цитата(MSDN)

There is no guarantee about the order in which threads will obtain ownership

Автор: Earnest 23.9.2007, 22:01
Цитата(iPlay @  23.9.2007,  22:10 Найти цитируемый пост)
Earnest, ты второй код прочитай.

А его не было еще, когда я ответ писала smile 

Цитата(iPlay @  23.9.2007,  22:10 Найти цитируемый пост)
JackYF, создал но всё равно сначало выводит потом меняет. 

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

Чтобы не зависеть от порядка создания потоков, одной критической секции недостаточно.
И вообще, критическая секция скорее предназначена для синхронизации обращения к общим данным. А здесь больше подойдет событие. Поток изменения по окончании должен установить его, а поток печати - ждать, пока оно не будет установлено.

Автор: iPlay 24.9.2007, 07:12
В том то всё и дело что я бы и сам сделал с событием но в задание просят критические секции (чтоб они были не лады). Ладно попробую чёто придумать.

Автор: dumb 24.9.2007, 08:51
Цитата(iPlay @  24.9.2007,  08:12 Найти цитируемый пост)
я бы и сам сделал с событием но в задание просят критические секции
крит.секцией ты должен обеспечить эксклюзивность доступа к файлу, а очередность делай через эвенты. задание б показал...

Автор: iPlay 24.9.2007, 17:57
Нужно синхронизировать два потока с помощью крит. секций. 1й поток выводит файл. 2й поток меняет содержимое файла. Я для проверки решил сначала поменять потом вывести и тут ниче не получается что бы я не делал всё равно сначала срабатывает поток вывода.

Автор: JackYF 24.9.2007, 18:39
Цитата(iPlay @  24.9.2007,  17:57 Найти цитируемый пост)
Я для проверки решил сначала поменять потом вывести и тут ниче не получается что бы я не делал всё равно сначала срабатывает поток вывода. 


тебе dumb всё верно сказал. Синхронизация != очередность доступа.

Автор: dumb 24.9.2007, 20:41
JackYF, причем то же самое выше было "озвучено" камрадами zkv и 
Earnest... smile

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