2014-10-04 5 views
2

부스트 라이브러리 (C++ 11 표준 이전)는 스레드에 대한 지원을 제공했습니다. 지원의 일환으로 동기화를 허용하는 단순한 클래스 인 "장벽"의 구현도 제공합니다. boost website :Boost 라이브러리가 스레드 장벽을 구현할 때 m_generation 변수를 사용하는 이유는 무엇입니까?

"장벽은 간단한 개념입니다. 랑데부라고도하며, 여러 스레드 간의 동기화 지점입니다. 장벽은 특정 수의 스레드 (n)에 대해 구성되며 스레드가 도달 할 때 구성됩니다 장벽은 모든 n 개의 쓰레드가 도착할 때까지 기다려야한다. 일단 n 번째 쓰레드가 장벽에 도달하면 모든 대기 쓰레드가 진행될 수 있고 장벽은 재설정된다. "

배리어 (대기)의 주요 기능의 구현 부스트 1.54로, 다음과 같다 :

는 배리어 재사용 것을 알 수있다

bool wait() 
{ 
    boost::mutex::scoped_lock lock(m_mutex); 
    unsigned int gen = m_generation; 

    if (--m_count == 0) 
    { 
     m_generation++; 
     m_count = m_threshold; 
     m_cond.notify_all(); 
     return true; 
    } 

    while (gen == m_generation) 
     m_cond.wait(lock); 
    return false; 
} 
일단 구성은 그렇지 않습니다 최초 사용 후 폐기해야합니다.

내 질문은 : 현재 m_generation 변수는 무엇입니까? 나는 부스트 라이브러리의 작가들이 그것을 포함시킬 이유가 있다고 가정하고있다. 장벽이 재설정/다시 사용할 준비가 될 때마다 증가하지만 끝까지 무엇입니까? 그것은 개인 변수이므로 외부에서 읽을 수 없습니다. 같은 문제는 private 클래스 변수를 가지지 않고 wait() 함수 내부의 간단한 내부 bool 변수로 쉽게 해결할 수 있습니다.

답변

5

간단히 말해 spurious wakeups을 처리하려면 m_generation이 필요합니다.

생성 카운터가 진행 자유롭게 배리어 기다리는 모든 스레드에 알리기 위해 상태 변수와 함께 사용된다 :

  • 번 배리어 도달 m_threshold 스레드가, 세대 번호가 부풀어오고 조건 변수가 신호됩니다. 이로 인해 대기중인 스레드 (즉, 이전에 장벽에 도달 한 스레드)가 m_cond.wait(lock)에서 깨어납니다.

  • 기다리는 스레드는 other reasons의 경우 m_cond.wait(lock)에서 깨울 수 있습니다. 여기가 m_generation입니다. 변경된 경우 장벽이 재설정되고 스레드가 진행될 수 있습니다. m_generation에 여전히 동일한 값이 포함되어 있으면 스레드를 m_cond.wait(lock)으로 다시 이동해야합니다.

wait() 안에 자동 변수가 있으면 각 스레드가 자체 인스턴스를 가지므로이 작업을 수행 할 수 없습니다.

+0

아! 고맙습니다. 내부 변수가 모든 인스턴스에 고유 한 인스턴스로 연결된다는 사실을 간과했다. 이제는 의미가 있습니다. 대단히 감사합니다. –