2017-03-22 17 views
1
#include <iostream> 
#include <mutex> 
#include <condition_variable> 
#include <thread> 
using namespace std; 
int num = 1; 
#define NUM 20 
condition_variable odd; 
condition_variable even; 
mutex mut; 
void thread_odd() 
{ 
     while(num < NUM -1) 
     { 
      if(num%2 != 1) 
      { 
        unique_lock<mutex> lock(mut); 
        odd.wait(lock); 
      } 
      cout<<"ODD : "<<num<<endl; 
      num++; 
      even.notify_all(); // Line X 
     } 
} 
void thread_even() 
{ 
     while(num < NUM) 
     { 
      if(num%2 != 0) 
      { 
        unique_lock<mutex> lock(mut); 
        even.wait(lock); 
      } 
      cout<<"EVEN : "<<num<<endl; 
      num++; 
      odd.notify_all(); 
     } 
} 
int main() 
{ 
     thread t1(thread_odd), t2(thread_even); 
     t1.join(); 
     t2.join(); 
     return 0; 
} 

/* 위의 내용은 ODD & EVEN 번호를 동기화 방식으로 (1 개씩) 인쇄하는 프로그램입니다. 코드는 대부분 잘 작동합니다. 하지만 때때로 교착 상황에 처해 있습니다. 이상한 스레드가 notify_all을 치고 있지만 짝수 스레드가 깨어나 기 전에 홀수 스레드가 잠금을 획득 한 후 대기 조건을 발견하면 짝수 스레드가 깨어나지 않은 동안 대기 상태가됩니다. 거래 상황에서 나가기. notify_all을 notify_one, 으로 바꾸려고 시도했지만 문제가 지속됩니다. 디자인에 필요한 변경 사항이 있습니까? 또는 내가 완전히 빠진 것이 있습니까? */notifyall이 C++ 멀티 스레딩에서 작동하지 않습니다. 교착 상태 발생

+0

'thread_odd()'가'even.notify_all()'을 호출하기 전에'thread_even()'이'even.wait()'을 호출하는지 확인해야합니다. – mkcms

답변

1

일반적으로 동시 프로그램에서 공유 리소스에 액세스하여 수정하고 수정하려는 경우 (예 : num의 모듈러스 연산자가 먼저 읽히고 num ++가 작성 됨), 다음을 수행해야합니다. 해당 리소스에 대한 상호 배타적 액세스 권한을 얻고 은 리소스가 완료 될 때까지을 릴리스하지 않습니다.

잠금이 if-statement 범위에있을 때 잠금이 해제되어이 규칙을 따르지 않습니다. 다음과 같이 코드를 수정하면

, 당신은 교착하지 않을 것이다 : 나는 통지하기 전에 잠금을 해제하고 방법

#include <iostream> 
#include <mutex> 
#include <condition_variable> 
#include <thread> 
using namespace std; 
int num = 1; 
#define NUM 20 
condition_variable odd; 
condition_variable even; 
mutex mut; 
void thread_odd() 
{ 
    while(num < NUM -1) 
    { 
     unique_lock<mutex> lock(mut); 
     if(num%2 != 1) 
     { 
      odd.wait(lock); 
     } 
     cout<<"ODD : "<<num<<endl; 
     num++; 
     lock.unlock(); 
     even.notify_all(); // Line X 
    } 
} 
void thread_even() 
{ 
    while(num < NUM) 
    { 
     unique_lock<mutex> lock(mut); 
     if(num%2 != 0) 
     { 
      even.wait(lock); 
     } 
     cout<<"EVEN : "<<num<<endl; 
     num++; 
     lock.unlock(); 
     odd.notify_all(); 
    } 
} 
int main() 
{ 
    thread t1(thread_odd), t2(thread_even); 
    t1.join(); 
    t2.join(); 
    return 0; 
} 

공지 사항. C++에서 이것은 (Java와는 대조적으로) 가능할뿐만 아니라, 강탈자가 중요 블록에 탐욕스럽게 다시 들어가게 할 가능성을 줄이기 때문에 권장됩니다. 이 마지막 지점 인 here에 대해 더 많은 통찰력을 얻을 수 있습니다.

+0

걸작. 그것을 생각해야합니다. 고맙습니다. – user3798283