2012-04-13 3 views
0

Я нашел код онлайн, который показывает, как использовать потоки из учебника от redKyle. В учебнике «Race Condition» он в основном показывает, как два потока передаются функции. Целью функции является печать «.» и '#' последовательно по сто раз. Он предоставляет код, чтобы заставить это работать, он НЕ предоставляет код для мьютекса. Я изменил код для включения мьютекса, чтобы предотвратить доступ одного потока к переменной, которая содержит последний символ, напечатанный, когда к нему обращается другой поток. Я получил код для работы. Большой! Тем не менее, я продолжал изменять значение спящего режима между 1 и 50. Код мьютекса работает нормально. Однако, когда я устанавливаю sleep на 0 (или просто комментируя это), мьютекс больше не работает, и значения больше не печатаются корректно (я больше не вижу 200 символов строго чередующихся «#» и «.»).Почему функция сна отключает мой Mutex

Ниже приведен код:

#include "stdafx.h" 

#include <iostream> 
#include <windows.h> 
using namespace std; 

static char lastChar='#'; 

//define a mutex 
HANDLE mutexHandle = NULL; 

//flag to specify if thread has begun 
bool threadStarted = false; 

void threadProc(int *sleepVal, int *threadID) 
{ 

    cout<<"sleepVal: "<<*sleepVal<<endl; 

    for (int i=0; i<100; i++) 
    { 

     char currentChar; 

     threadStarted = true; 

     while(!threadStarted){} 

     //lock mutex 
     WaitForSingleObject(mutexHandle, INFINITE); 

     if (lastChar == '#') 
      currentChar = '.'; 
     else 
      currentChar = '#'; 

     Sleep(*sleepVal); 

     lastChar = currentChar; 

     ReleaseMutex(mutexHandle); 

     threadStarted = false; 


     //  cout<<"\nSleepVal: "<<*sleepVal<<" at: "<<currentChar; 
     cout<<currentChar; 
    }//end for 
}//end threadProc 

int main() 
{ 
    cout<<"Race conditions by redKlyde \n"; 

    int sleepVal1 = 50; 
    int sleepVal2 = 30; 

    //create mutex 
    mutexHandle = CreateMutex(NULL, false, NULL); 

    //create thread1 
    HANDLE threadHandle; 
    threadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) threadProc, &sleepVal1, 0, NULL); 

    //create thread2 
    HANDLE threadHandle2; 
    threadHandle2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) threadProc, &sleepVal2, 0, NULL); 

    WaitForSingleObject(threadHandle, INFINITE); 
    WaitForSingleObject(threadHandle2, INFINITE); 

    cout<<endl<<endl; 

    CloseHandle(mutexHandle); 

    system("pause"); 

    return 0; 

} 

Так что мой вопрос: почему установка сна 0 к аннулированию кода мьютекса.

ответ

1

Обратите внимание, что ваш оператор печати не защищен мьютексом, поэтому один поток можно распечатать, а другой можно изменить. Не спать, вы позволяете планировщику определять порядок печати на основе кванта потока.

Есть некоторые вещи неправильно:

1) Вы не должны спать внутри удерживаемого замка. Это почти никогда не бывает правильным. 2) В любом месте, где ваши данные являются общими, вы должны быть защищены с помощью блокировки. Это означает, что оператор печати также должен находиться в замке.

+0

ОК большой, чемкс Сан-Хасинто. Я снял сон из замка и включил инструкцию печати в замок. работает красиво и делает гораздо больше смысла! –

1

Кроме того, в качестве подсказки для будущего использования взаимного исключения в Windows лучшим мьютексом usermode является SRWLock, за которым следует CriticalSection. Использовать синхронизирующий объект на основе ручек намного медленнее.

Смежные вопросы