2009-08-19 4 views
3

thread_group::create_thread()을 생성하고 쓰레드를 생성하기 위해 boost::thread_group을 사용하고 있습니다. 최대 스레드 수를 각 스레드의 끝에 제한하기 위해 thread_group에서 스레드 을 제거하고 스레드 자체를 삭제합니다 (따라서 새 스레드를 생성해야하는지 여부를 결정할 수 있음). 그러나 마지막 스레드 (예 : 999 번째 999 번째 합계)의 생성과 삭제 사이에 이 있습니다.boost.thread 데드 록 및 자기 삭제

내 질문은 :

  • 그것이 내가하는 일처럼 자체 내에서 에서 스레드를 삭제 OK인가? 이 아닌 경우 달성 할 수있는 가장 좋은 방법
  • 왜 코드가 중단됩니까? 이하

는 관련 코드이다 : 만들

// 1- 코드 및 송출 스레드 스레드 실행

{ 
     //mutex for map<thread_id, thread*> operations 
     boost::mutex::scoped_lock lk(m_mutex_for_ptr); 

     // create a thread for this->f(duplicate_hashes) 
     boost::thread* p = m_thread_group.create_thread(boost::bind( 
      &detectiveT<equal_predicate>::f, 
      this, 
      duplicate_hashes 
      )); 

     // save the <thread_id,thread pointer> map for later lookup & deletion 
     m_thread_ptrs.insert(make_pair(p->get_id(), p)); 

     // log to console for debug 
     cout << "thread created: " 
      << p->get_id() << ", " 
      << m_thread_group.size() << ", " m_thread_ptrs.size() << 
"\n";  
    } 

// 2- 코드

void f(list<map_iterator_type>& l) 
{ 
    Do_something(l);  
    boost::this_thread::at_thread_exit(boost::bind( 
     &detectiveT<equal_predicate>::remove_this_thread, 
     this 
     ));      
} 

// 3 코드는 스레드 자체를 삭제합니다.

void remove_this_thread() 
{ 

    { 
     //mutex for map<thread_id, thread*> operations 
     boost::mutex::scoped_lock lk(m_mutex_for_ptr);     
     boost::thread::id this_id(boost::this_thread::get_id()); 

     map<boost::thread::id, boost::thread*>::iterator itr; 

     itr = (m_thread_ptrs.find(this_id)); 

     if(m_thread_ptrs.end() != itr) 
     { 
      // remove it from the control of thread_group 
      m_thread_group.remove_thread(itr->second); 
      // delete it 
      delete itr->second; 

      // remove from the map 
      m_thread_ptrs.erase(this_id); 

      // log to console for debug 
      cout << "thread erased: " 
       << this_id << ", " 
       << m_thread_group.size() << ", " 
       << m_thread_ptrs.size() << "\n";    
     } 
    }    
} 
+0

? procexp.exe의 –

+0

에서 모든 스레드가 "대기 : UserRequest"상태에 있음을 알 수 있습니다. thread_group 내부 잠금과 소개하는 외부 잠금 (즉, lk (m_mutex_for_ptr))간에 재귀 잠금이 발생한다고 생각하지만 확실하지 않습니다. 나는이 행을 주석 처리함으로써 운이 좋았습니다. <<< m_thread_group.size() << >>, void_retis_thread()에서 그 행을 재현 할 수 없었습니다. –

+0

@ Lightness Races in Orbit :'detach() '스레드에서 삭제하고 개체를 삭제하십시오. 그러면 스레드가 종료 될 때 스레드가 자원을 자동으로 해제합니다 (http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_create.3.html 참조). 그렇지 않으면 아무도 종료 할 때 아무도 참여하지 못하기 때문에 스스로 결합하여 교착 상태가되거나 좀비가됩니다. –

답변

4

작성/삭제 비용이 비싸므로 스레드를 재활용하려고하지 않는 이유는 무엇입니까?

스레드 풀 클래스를 코딩하고 스레드 풀 클래스에 작업을 보냅니다. 풀은 사용 가능한 스레드가 더 이상 없으면 작업을 큐에 넣거나 current_threads < max_threads 인 경우 스레드를 만들거나 사용 가능한 스레드를 사용합니다.

제안 사항 :

이상적인 개수의 스레드를 확인하십시오. 이것은 대개 프로세서 수와 같습니다. 원하는 복잡도에 따라 풀의 모든 스레드를 한 번에 만들거나 current-thread-count < ideal-thread-count 및 모든 기존 스레드가 작업을 실행 중일 경우 스레드를 추가 할 수 있습니다.

모든 스레드를 한꺼번에 작성한다고 가정하면 실행할 각 스레드에 작업자 함수를 전달해야합니다. 이 작업자 함수는 작업이 사용 가능해질 때까지 기다린 다음 실행합니다. 함수가 작업을 실행하거나 기다리는 경우 반환하지 않으므로 스레드가 파괴되지 않습니다..

스레드 풀은 작업 큐를 추적하고 큐에서 사용할 수있는 작업이있는 경우를 나타내는 대기 조건을 관리 할 수 ​​있습니다. 각 스레드 작업자 함수는 대기 조건을 기다리고 사용 가능한 태스크가있을 때 깨어나서 작업을 시도합니다. 일부 동기화를 수행해야합니다. 가장 쉬운 방법은 사용 가능한 스레드 풀 구현을 찾는 것일 것입니다 (Windows + Vista). 또는 QtConcurrent에서 작업을 전달하고 실행을 호출하여 OS/라이브러리를 걱정하게 할 수 있습니다 모두.

나중에 편집 :

체크 아웃 디버거에서 프로그램을 실행하면, 어떤이가 달려 다양한 스레드에서 어떤 일이 일어나고 http://threadpool.sourceforge.net/

+0

스레드를 재활용하는 방법을 자세히 설명해 주시겠습니까? 내 경험에 따르면 스레드의 실행은 ctor와 함께 전달되므로 스레드를 변경하고이 스레드 객체를 다시 사용하는 방법은 없습니다. –

+0

나를 계몽 해 주셔서 감사합니다. 나는 Boost.Task를 발견했으며 그것을 얼마나 활용할 수 있는지 시험 할 것입니다. –

+0

직접 내 질문에 답변하지는 않았지만, 내 문제를 무효화하는 더 좋은 방법을 제안했습니다. 그래서 나는 당신의 대답을 대답으로 받아 들였다. 감사. –