2017-04-03 3 views
1

내가 원시 동기화 개체를 사용하여 C++에서 생산자 - 소비자 문제를 해결해야 할 사건은 이미이 코드C++에서 winapi 이벤트를 사용하여 Producer-Consumer를 해결하는 방법은 무엇입니까? 나는이 코드를 해결할 수있는 방법 무한주기 을 가지고있다 -

static int g_x = 0; 
HANDLE hEvent1; 

HANDLE aThread[2]; 
DWORD ThreadID; 

//tread 1 
void Producer() 
{ 
    for (int i = 0; i < 100; ++i) 
    { 
     WaitForSingleObject(hEvent1, INFINITE); 
     g_x = i; 
     SetEvent(hEvent1); 
    } 
} 
//thread 2 
void Consumer() 
{ 
    for (;;) 
    { 
     WaitForSingleObject(hEvent1, INFINITE); 
     SetEvent(hEvent1); 
    } 
} 

int createthreads() { 
    hEvent1 = CreateEvent(NULL, FALSE, TRUE, NULL); 

    // Create worker threads 
    aThread[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Producer, NULL, 0, &ThreadID); 
    aThread[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Consumer, NULL, 0, &ThreadID); 
} 
int main() { 
    createthreads(); 
} 

이 코드가 제대로 작동하지 않습니다를 썼다 콘솔 번호를 0에서 99으로 변경 하시겠습니까?

+0

https://msdn.microsoft.com/en-us/library/windows/desktop/ms686903(v=vs.85).aspx –

+0

https://msdn.microsoft.com/en-us /library/windows/desktop/aa904937(v=vs.85).aspx –

+0

은 2 개의 이벤트를 사용해야합니다. – RbMm

답변

1

이 두 스레드를 동기화하려면 다른 이벤트가 필요합니다. 또한 두 개의 이벤트의 초기 상태를 FALSE으로 설정하고 main의 생산자 스레드에 시작 이벤트를 보냅니다.
이렇게하면 프로세스가 시작되는시기와 방법을 제어 할 수 있습니다.

Offtopic, createthreads은 값을 반환해야합니다.

static int g_x = 0; 
HANDLE hEvent1; 
HANDLE hEvent2; 

HANDLE aThread[2]; 
DWORD ThreadID; 

//tread 1 
void Producer() 
{ 
    for (int i = 0; i < 100; ++i) 
    { 
     WaitForSingleObject(hEvent1, INFINITE); 
     g_x = i; 
     SetEvent(hEvent2); 
    } 
} 
//thread 2 
void Consumer() 
{ 
    for (;;) 
    { 
     WaitForSingleObject(hEvent2, INFINITE); 
     SetEvent(hEvent1); 
    } 
} 

int createthreads() { 
    hEvent1 = CreateEvent(NULL, FALSE, FALSE, NULL); 
    hEvent2 = CreateEvent(NULL, FALSE, FALSE, NULL); 

    // Create worker threads 
    aThread[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Producer, NULL, 0, &ThreadID); 
    aThread[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Consumer, NULL, 0, &ThreadID); 
    return 0; 
} 
int main() { 
    createthreads(); 
    SetEvent(hEvent1); 
} 
+0

'createthreads는 값을 반환해야합니다 - 하나의 매개 변수로 * __ stdcall *이어야합니다) – RbMm

+0

두 스레드가 시작됩니다 from * WaitForSingleObject * -이 경우 둘 다 중지되었습니다. * SetEvent * 첫 번째 호출이 필요합니다. – RbMm

+0

@RbMm, 네, 바로 그게 필요합니다! – Rama

0

존재하는 여러 가지 방법으로이 작업을 구현할 수 있습니다. 한 가지 가능한 경우 - 이벤트 쌍 -2 이벤트를 사용해야합니다.

struct EventPair 
{ 
    HANDLE hLowEvent, hHighEvent; 

    ~EventPair() 
    { 
     if (hHighEvent) CloseHandle(hHighEvent); 
     if (hLowEvent) CloseHandle(hLowEvent); 
    } 

    EventPair() 
    { 
     hLowEvent = 0, hHighEvent = 0; 
    } 

    DWORD Create() 
    { 
     return (hLowEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) && 
      (hHighEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) ? NOERROR : GetLastError(); 
    } 
}; 

struct SharedData : EventPair 
{ 
    int _x; 
    bool _quit; 

    SharedData() 
    { 
     _x = 0; 
     _quit = false; 
    } 

    static DWORD WINAPI _Producer(void* This) 
    { 
     reinterpret_cast<SharedData*>(This)->Producer(); 
     ExitThread(0); 
    } 

    void Producer() 
    { 
     for (int i = 0; ;) 
     { 
      _x = i++; 
      if (i == 100) 
      { 
       _quit = true; 
      } 
      SetEvent(hLowEvent); 
      if (_quit) 
      { 
       return; 
      } 
      WaitForSingleObject(hHighEvent, INFINITE); 
     } 
    } 

    static DWORD WINAPI _Consumer(void* This) 
    { 
     reinterpret_cast<SharedData*>(This)->Consumer(); 
     ExitThread(0); 
    } 

    void Consumer() 
    { 
     for(;;) 
     { 
      WaitForSingleObject(hLowEvent, INFINITE); 
      DbgPrint("%u\n", _x); 
      if (_quit) 
      { 
       return; 
      } 
      SetEvent(hHighEvent); 
     } 
    } 
}; 

void testPC() 
{ 
    SharedData sd; 
    if (!sd.Create()) 
    { 
     HANDLE hThreads[2] = {}; 
     if (hThreads[0] = CreateThread(0, 0, SharedData::_Producer, &sd, 0, 0)) 
     { 
      if (hThreads[1] = CreateThread(0, 0, SharedData::_Consumer, &sd, 0, 0)) 
      { 
       WaitForMultipleObjects(2, hThreads, TRUE, INFINITE); 
       CloseHandle(hThreads[1]); 
      } 
      else 
      { 
       sd._quit = true; 
       SetEvent(sd.hHighEvent); 
       WaitForSingleObject(hThreads[0], INFINITE); 
      } 
     } 
     CloseHandle(hThreads[0]); 
    } 
}