Критические секции

Тема в разделе "WASM.WIN32", создана пользователем Benzin, 7 апр 2008.

  1. Benzin

    Benzin Сергей

    Публикаций:
    0
    Регистрация:
    26 авг 2007
    Сообщения:
    41
    Адрес:
    St.Petersburg
    Народ, помогите плиз, только начал изучать синхронизацию потоков, а именно: критические секции.
    Чтоб все освоить на практике, пытаюсь сделать след. программку: имеется общий ресурс: переменная типа FILE, также имеется 2 потка: первый - создает файл и записывает туда числа от 0 до 4, второй - редактирует этот файл и пишет числа от 0 до 9.
    Проблема собственно с критическими секциями. Сначала у меня было без использования критических секций, но потоки работали некорректно, т.е в файл писался мусор, тогда я добавил Sleep(20) во второй поток, и все стало нормально, но вообще то так же не делается, и вот когда я дошел до изучения критических секций, то подумал, что раз такое существует, то каждый процесс надо туда затолкать и тогда процессы выполнятся корректно, но у меня возникли проблемы, что не так делаю, подскажите:
    Код (Text):
    1. DWORD WINAPI WriteMyFile_1();
    2. DWORD WINAPI WriteMyFile_2();
    3.  
    4. //общий ресурс
    5. FILE *F;
    6.  
    7. //Объявление структуры критичесокй секции
    8. CRITICAL_SECTION cs_file;
    9.  
    10.  
    11. int main()
    12. {
    13.     //Создаем первый поток, который запишет в файл
    14.     HANDLE hWriteThread = BeginThreadEx(NULL,NULL, &WriteMyFile_1, NULL,NULL,NULL);
    15.     CloseHandle(hWriteThread);
    16.     //Создаем второй поток, который запишет в файл
    17.     HANDLE hReadThread = BeginThreadEx(NULL,NULL, &WriteMyFile_2, NULL,NULL,NULL); 
    18.     CloseHandle(hReadThread);
    19. }
    20.  
    21. DWORD WINAPI WriteMyFile_1()
    22. {
    23.     //Иницаализация элементов структуры CRITICAL_SECTION
    24.     InitializeCriticalSection(&cs_file);
    25.    
    26.     //Открываем критическую секцию
    27.     EnterCriticalSection(&cs_file);
    28.        
    29.     F = fopen("MyFileTest.txt", "w");
    30.        
    31.     //проверка
    32.     if(F == NULL)
    33.     {
    34.         MessageBox(hDlg1,"Файл не был создан","Error",MB_ICONHAND|MB_OK);
    35.     }
    36.        
    37.     TCHAR bufThread_1[]="Начало выполнения первого потока";
    38.     fprintf(F,"%s\n", bufThread_1); //Записываем начало исполнения первого потока
    39.    
    40.     for (int one=0; one<5; one++)
    41.     {
    42.         fprintf(F,"%d\n", one); //и записывать в файл  значения от 0 до  5
    43.     }
    44.     fclose(F);
    45.  
    46.     //Закрываем критическую секцию
    47.     LeaveCriticalSection(&cs_file);
    48.    
    49.     return 0;
    50. }
    51.  
    52. DWORD WINAPI WriteMyFile_2()
    53. {
    54.     //Иницаализация элементов структуры CRITICAL_SECTION
    55.     InitializeCriticalSection(&cs_file);
    56.  
    57.     //Открываем критическую секцию
    58.     EnterCriticalSection(&cs_file);
    59.        
    60.     F = fopen("MyFileTest.txt", "a");
    61.        
    62.     //проверка
    63.     if(F == NULL)
    64.     {
    65.         MessageBox(hDlg1,"Файл не был создан","Error",MB_ICONHAND|MB_OK);
    66.     }
    67.        
    68.     TCHAR bufThread_2[]="Начало выполнения второго потока";
    69.     fprintf(F,"%s\n", bufThread_2); //Записываем начало исполнения второго потока
    70.        
    71.     for (int one=0; one<10; one++)
    72.     {
    73.         fprintf(F,"%d\n", one); //и записывать в файл значения от 0 до 10
    74.     }
    75.     fclose(F);
    76.  
    77.     //Закрываем критическую секцию
    78.     LeaveCriticalSection(&cs_file);
    79.  
    80.     return 0;
    81. }
     
  2. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    А где InitializeCriticalSection?
     
  3. asd

    asd New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2005
    Сообщения:
    952
    Адрес:
    Russia
    Benzin
    + interloked ф-ии тут не нужны, раз всё обёрнуто в критические секции.
     
  4. Benzin

    Benzin Сергей

    Публикаций:
    0
    Регистрация:
    26 авг 2007
    Сообщения:
    41
    Адрес:
    St.Petersburg
    Booster пойду тогда дальше изучать, как что так сразу приду =)
     
  5. Benzin

    Benzin Сергей

    Публикаций:
    0
    Регистрация:
    26 авг 2007
    Сообщения:
    41
    Адрес:
    St.Petersburg
    Отредактировал исходник, добавл InitializeCriticalSection, но все равно не совсем так:
    все равно запись идет некорректно, т.е сначала все нормально, когда первый раз, то пишется как надо:

    Код (Text):
    1. Начало выполнения первого потока
    2. 0
    3. 1
    4. 2
    5. 3
    6. 4
    7. Начало выполнения второго потока
    8. 0
    9. 1
    10. 2
    11. 3
    12. 4
    13. 5
    14. 6
    15. 7
    16. 8
    17. 9
    Т.е. и 1 и 2 поток все записывают, но бывает, что записываетя и так:
    Код (Text):
    1. Начало выполнения первого потока
    2. 0
    3. 1
    4. 2
    5. 3
    6. 4
    7. 5
    8. 6
    9. 7
    10. 8
    11. 9
    Т.е. первая фраза из 1-го потока, а остальное из 2, как может такое происходить, если критические секции и предназначены для того чтобы ограничить доступ 2 потока пока выполняется 1, т.е получается так что первый вытесняется системой, а тут подошло время второго и он сразу же записывает, что по идее то не должен делать, система же должна запомнить то место на котором закончил свое выполнение первый поток, потом опять выделить ему время, а потом уже только второму... я так понимаю.
    Конечно можно было бы решить это с помощью приоритета потоков, но мне же важно разобраться именно в крит. секциях, как сделать задуманное, не приостанавливая второй поток вызовом Sleep, и не повышая приореты потоков?
    Объясните пож-та, ну ни как не вкуриваю чё то.. =(

    И в добавку:
    если я вызвал InitializeCriticalSection, то надо и удалить эл-ты этой структуры вызовом DeleteCriticalSection, только где ее вызвать?
     
  6. asd

    asd New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2005
    Сообщения:
    952
    Адрес:
    Russia
    Benzin
    Код в студию. И ещё если ты создаёшь первым поток WriteMyFile_1, это не значит, что он первым займёт критическую секцию. + Рихтера почитай.
     
  7. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Да Рихтер есть гуд. После прочтения его книги у меня отпали вопросы даже которых не было -)
     
  8. Benzin

    Benzin Сергей

    Публикаций:
    0
    Регистрация:
    26 авг 2007
    Сообщения:
    41
    Адрес:
    St.Petersburg
    я ж выше написал весь кусок. Пришлось создать новый проект =) (в прикрипленных)
    Его и штудирую =)
     
  9. asd

    asd New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2005
    Сообщения:
    952
    Адрес:
    Russia
    InitializeCriticalSection нужно вызывать 1 раз до создания потоков, которые будут использовать её
     
  10. ALLeX

    ALLeX Member

    Публикаций:
    0
    Регистрация:
    21 окт 2004
    Сообщения:
    141
    Адрес:
    Ukraine