3

スレッドのboost::thread_group作成(使用 )とディスパッチに使用しています。thread_group::create_thread()最大スレッド数を制限するために、各スレッドの最後で、からスレッドthread_groupを削除し、スレッド自体を削除します(新しいスレッドを作成する必要があるかどうかを判断できるようにするため)。ただし、最後のスレッドの作成と削除の間のどこかでハングします(たとえば、合計999の999番目のスレッド)。

私の質問は次のとおりです。

  • 私のようにスレッド自体からスレッドを削除しても大丈夫ですか?そうでない場合、これを達成するための最良の方法は何ですか
  • コードがハングするのはなぜですか?

関連するコードは次のとおりです。

//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";             
        } 
    }               
}
4

1 に答える 1

4

作成/破棄には費用がかかるので、スレッドをリサイクルしてみませんか?

スレッドプールクラスをコーディングし、それにタスクを送信します。プールは、使用可能なスレッドがなくなった場合にタスクをキューに入れるか、current_threads <max_threadsの場合にスレッドを作成するか、使用可能なスレッドを使用します。

推奨される実装:

理想的なスレッド数を確認してください。これは通常、プロセッサの数と同じです。これをどれだけ複雑にするかに応じて、プール内のすべてのスレッドを一度に作成するか、current-thread-count <ideal-thread-countであり、既存のすべてのスレッドがタスクの実行でビジーの場合はスレッドを追加できます。

すべてのスレッドを一度に作成していると仮定すると、実行する各スレッドにワーカー関数を渡す必要があります。このワーカー関数は、タスクが使用可能になるのを待ってから実行します。関数はタスクを実行するか、タスクを待機するため、タスクは返されず、スレッドは破棄されません

スレッドプールは、タスクキューを追跡し、キューに使用可能なタスクがあることを示す待機条件を管理できます。各スレッドワーカー関数は待機条件で待機し、使用可能なタスクがあると、ウェイクアップしてタスクを実行しようとします。同期を行う必要があります。最も簡単な方法は、Windows(Vista +だと思います)やQtConcurrentのような、利用可能なスレッドプールの実装を見つけて、タスクを渡し、runを呼び出して、OS/ライブラリに心配させることです。すべての。

後で編集:

http://threadpool.sourceforge.net/をチェックしてください

于 2009-08-19T13:04:32.227 に答える