2014-12-05 2 views
1

누군가 내가 잘못하고있는 것을 지적 할 수 있습니까?
foo와 bar를 교대로 인쇄하고 싶습니다.
때로는 첫 번째 반복에서 멈추고 어떤 경우에는 멈추기 전에 잠시 동안 계속됩니다.양방향 통신을위한 조건 변수를 사용할 때 교착 상태가 발생했습니다.

#include <thread> 
#include <mutex> 
#include <condition_variable> 
std::mutex m; 
std::condition_variable cv; 
void foo() 
{ 
    while(true) 
    { 
     std::unique_lock<std::mutex> ul(m); 
     cv.wait(ul); 
     std::cout<<"bar"<<std::endl; 
     ul.unlock(); 
     cv.notify_one(); 
    } 
} 
int main() 
{ 
    std::thread t(foo); 
    while(true) 
    { 
     std::cout<<"foo"<<std::endl; 
     cv.notify_one(); 
     std::unique_lock<std::mutex> ul(m); 
     cv.wait(ul); 
    } 
} 
+0

당신은 실제 통신을 잊었다! 뮤텍스가 있지만 아무것도 보호하지 않습니다! –

답변

1

조건 변수는 변경 사항을 알려주지 만 그 자체로는별로 유용하지 않습니다. 그것을 상태와 결합해야합니다.

누구의 차례인지 지시하는 또 다른 변수를 추가하십시오.

std::mutex m; 
std::condition_variable cv; 
int turn = 0; 

void foo() 
{ 
    while(true) 
    { 
     std::unique_lock<std::mutex> ul(m); 
     if(turn == 1) { 
      // my turn 
      std::cout << "bar" << std::endl; 

      // tell them it's their turn 
      turn = 0; 
      cv.notify_one(); 
     } else { 
      // not our turn, wait for a change. 
      cv.wait(ul); 
     } 
    } 
} 

int main() 
{ 
    std::thread t(foo); 
    while(true) 
    { 
     std::unique_lock<std::mutex> ul(m); 
     if(turn == 0) { 
      // my turn 
      std::cout << "foo" << std::endl; 

      // tell them it's their turn 
      turn = 1; 
      cv.notify_one(); 
     } else { 
      // not our turn, wait for a change. 
      cv.wait(ul); 
     } 
    } 
} 

뮤텍스는 turn 변수에 대한 안전한 액세스를 위해 사용되며,이 변경된 때마다 다른 스레드가 일어나 새로운 값을 확인할 수 있도록, 당신은 조건 변수를 통지합니다.


편집 : 당신이 당신의 퍼즐을 해결하기 위해, 위의 내용을 이해 가정 : 즉

void foo() 
{ 
    std::unique_lock<std::mutex> ul(m); 
    while(true) 
    { 
     std::cout << "bar" << std::endl; 
     cv.notify_one(); 
     cv.wait(ul); 
    } 
} 

int main() 
{ 
    std::unique_lock<std::mutex> ul(m); 
    std::thread t(foo); 
    while(true) 
    { 
     std::cout << "foo" << std::endl; 
     cv.notify_one(); 
     cv.wait(ul); 
    } 
} 

을, 당신은 당신이 하위 스레드를 시작하기 전에, 루프의 외부에서 뮤텍스를 잠글 필요 , 차례가 가장 먼저 나오는 논리는 분명합니다. 그런 다음 작업을 수행하고 조건을 알린 다음 다른 스레드가 신호를 보내길 기다립니다. 논리의

흐름 :

Main Thread    Sub Thread 
------------------------------------------ 
Lock Mutex 

Create Subthread 

         Try to lock mutex 
         but it is busy. 

Print "foo"    ...waiting for mutex... 

Notify cvar    ignores notification, 
         (still waiting for mutex) 

Wait on cvar   Obtains lock 
         (when waiting on a cvar, the lock is released.) 

...waiting...   Prints "bar" 

Notified, but the  Notify cvar 
mutex is still locked   
so we are waiting. 

Obtains lock again  Wait on cvar 

Print "foo"    ...waiting... 

(etc...) 
+0

두 번째 예제처럼 메인에서 뮤텍스를 잠그는 것이 좋습니다. 왜 내가 추가 회전 플래그를 가져야합니까? – manasij7479

+0

두 번째 예제가 작동하는 동안 실용적인 시나리오에서보다 유용합니다. 전혀 유연하지 않습니다 – mukunda

+0

다른 스레드가 알림을 기다리지 않고 계속 작동하지 않는 한. 즉, 다중 스레드가 아닙니다. – mukunda

0

우물. main을 호출하면 notify을 호출하고 foonotify을 호출하고 main은 뮤텍스를 잠그고 대기 한 다음 뮤텍스에서 foo 블럭을 호출합니다. 이중 자물쇠.

+0

이 통신을 어떻게 성취합니까? – manasij7479