2012-03-06 1 views
4

boost :: thread의 조합법을 배우기 위해 공통 뮤텍스 (M)를 잠그는 스레드에 간단한 장벽 (BR)을 구현했습니다. 그러나 BR.wait()에 갈 때 뮤텍스의 잠금은 해제되지 않으므로 모든 스레드가 BR에 도착하도록하려면 M에 대한 잠금을 수동으로 해제해야합니다. 그래서 나는 다음과 같은 코드가 있습니다 :수동으로 부스트 잠금을 해제 하시겠습니까?

boost::barrier BR(3); 
boost::mutex M; 

void THfoo(int m){ 
    cout<<"TH"<<m<<" started and attempts locking M\n"; 
    boost::lock_guard<boost::mutex> ownlock(M); 

    cout<<"TH"<<m<<" locked mutex\n"; 
    Wait_(15); //simple wait for few milliseconds 

    M.unlock(); //probably bad idea 
    //boost::lock_guard<boost::mutex> ~ownlock(M); 
    // this TH needs to unlock the mutex before going to barrier BR 

    cout<<"TH"<<m<<" unlocked mutex\n"; 
    cout<<"TH"<<m<<" going to BR\n"; 
    BR.wait(); 
    cout<<"TH"<<m<<" let loose from BR\n"; 
} 

int main() 
{ 
    boost::thread TH1(THfoo,1); 
    boost::thread TH2(THfoo,2); 
    boost::thread TH3(THfoo,3); 

    TH2.join(); //but TH2 might end before TH1, and so destroy BR and M 
    cout<<"exiting main TH \n"; 

    return 0; 
} 

M.unlock()가 명확하게 (잠금을 사용하지 않는) 나쁜 솔루션입니다 반면; 그래서 (단순히) 자물쇠를 해제하는 방법? 또한 : 어떻게 maint()에서 (모든) 스레드가 완료 될 때까지 (올바르게) 기다려야합니까? (TH2.join()이 나쁘다. 왜냐하면 TH2가 먼저 끝날 수 있기 때문이다.);

다음과 같은 내용을 제안하지 마십시오. 조건부 변수를 사용할 수도 있지만, 직접 변수없이 수행 할 수 있어야합니다.

답변

4

뭔가 같은 :

void THfoo(int m){ 
    // use a scope here, this means that the lock_guard will be destroyed (and therefore mutex unlocked on exiting this scope 
    { 
    cout<<"TH"<<m<<" started and attempts locking M\n"; 
    boost::lock_guard<boost::mutex> ownlock(M); 

    cout<<"TH"<<m<<" locked mutex\n"; 
    Wait_(15); //simple wait for few milliseconds 

    } 
    // This is outside of the lock 
    cout<<"TH"<<m<<" unlocked mutex\n"; 
    cout<<"TH"<<m<<" going to BR\n"; 
    BR.wait(); 
    cout<<"TH"<<m<<" let loose from BR\n"; 
} 

대기에 관해서는, 단순히 이미 완료 한 경우 (모든 스레드 핸들에 가입 호출합니다 기능은

+0

쿨, 고마워요 ... –

1

이 범위를 벗어나 가자 :

void THfoo(int m){ 
    cout<<"TH"<<m<<" started and attempts locking M\n"; 
    { 
     boost::lock_guard<boost::mutex> ownlock(M); 

     cout<<"TH"<<m<<" locked mutex\n"; 
     Wait_(15); //simple wait for few milliseconds 
    } 

    // this TH needs to unlock the mutex before going to barrier BR 

    cout<<"TH"<<m<<" unlocked mutex\n"; 
    cout<<"TH"<<m<<" going to BR\n"; 
    BR.wait(); 
    cout<<"TH"<<m<<" let loose from BR\n"; 
} 
1
cout<<"TH"<<m<<" started and attempts locking M\n"; 
{ 
    boost::lock_guard<boost::mutex> ownlock(M); 

    cout<<"TH"<<m<<" locked mutex\n"; 
    Wait_(15); //simple wait for few milliseconds 

} //boost::lock_guard<boost::mutex> ~ownlock(M); 
// this TH needs to unlock the mutex before going to barrier BR 

cout<<"TH"<<m<<" unlocked mutex\n"; 
) 즉시 반환한다3210

모든 스레드가 join 인 경우 TH2가 처음 완료 될 때 유일한 문제는 TH2가 join에 의해 "수확 될"수 있고 반환 값과 같은 남은 리소스가 해제되기 전에 TH1이 실행을 완료해야한다는 것입니다. 3 개의 스레드에 대해 걱정할 필요가 없습니다. 메모리 사용이 문제가 있다면 timed_join을 사용하여 차례로 모든 스레드를 반복적으로 시도 할 수 있습니다.

또한 주 스레드가 조건 변수를 기다리고, 각 스레드가 완료되면 완료 될 때까지 값을 저장하고 주 변수가 주 변수를 전달할 수 있도록 신호를 보냅니다. 쓰레드는 join입니다. 스레드가 신호를 보낼 것이라는 것을 절대 확신해야합니다. 그렇지 않으면 영원히 기다릴 수 있습니다. 따라서 스레드를 취소하는 경우 조심하십시오.

+0

저는 M과 BR에 대해 걱정이됩니다. main() 종료 후에 나머지 TH에 액세스 할 수 없게됩니다. 그래서 문제는 올바르게 수행하는 방법입니다. 따라서 충돌 위험이 결코 발생하지 않습니다. 모든 스레드의 "timed_join"이 대답 일 것이라고 생각하십니까? –

+0

@PMarecki : 특별한 이유가 없다고 생각할 수 없다면, 그냥 TH1.join(); TH2.join(); TH3.join();'.그렇다면'main'은 쓰레드가 실행 중일 때 리턴하지 않습니다 (던질 수도 있음). 시작하는 모든 스레드를 결합하거나 분리 할 계획을 세워야합니다. 'boost :: thread'의 소멸자는 어떤 경우 든 그것들을 분리시킬 것이고, 나는 그것이 전역이 파괴되기 전에 끝내야한다는 것을 의미한다고 생각합니다. 그러나 당신이 다르게보고 있다면, 아마도 나는 틀 렸습니다. –

1

boost :: lock_guard 대신 boost :: mutex :: scoped_lock을 사용하면 unlock() 메소드가 있습니다. 호출하면 잠금은 소멸자에서 다시 잠금 해제를 시도하지 않습니다. 자물쇠를 자체 블록에 배치하는 것보다 코드를 더 맛있게 보았습니다.

+0

조금 추가하려면 : 질문에서와 같이 기본 뮤텍스에서 unlock()을 호출하면 lock_guard가 범위를 벗어날 때 unlock()이 다시 호출됩니다. scoped_lock (또는 비슷한)을 사용하고 unlock()을 호출하면 범위를 벗어날 때 두 번째 잠금을 해제하지 않습니다. – RobH

+0

블록 (및 수반하는 들여 쓰기)이 인터리빙 함수 호출보다 _lot_ 더 명확하다는 것을 알았습니다 –

8

블록에 boost::lock_guard 범위를 지정하는 것 외에도, 당신은 또한 'unlock() 될 수 boost::unique_lock 명시 적으로 에드 사용할 수 있습니다 나중에 재 취득하기 전에 뮤텍스를 해제해야하는 경우

boost::unique_lock<boost::mutex> ownlock(M); 

cout<<"TH"<<m<<" locked mutex\n"; 
Wait_(15); //simple wait for few milliseconds 

ownlock.unlock(); 

이 유용합니다.

가입의 경우 모든 스레드 핸들에서 차례대로 join()을 호출하면됩니다.

+1

unique_lock에 대한 의견을 보내 주셔서 감사합니다. 감사! –