Вопрос

Я использую 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";             
        } 
    }               
}
Это было полезно?

Решение

Почему бы вам не попробовать переработать потоки, поскольку создание / уничтожение обходится дорого?

Закодируйте класс пула потоков и отправляйте в него задачи.Пул либо поставит задачи в очередь, если у него больше нет доступных потоков, либо создаст потоки, если current_threads < max_threads или просто используйте тот поток, который доступен.

Предлагаемая реализация:

Узнайте, каково ваше идеальное количество потоков.Обычно это равно количеству процессоров.В зависимости от того, насколько сложным вы хотите, чтобы это было, вы могли бы создать все потоки в пуле сразу или добавить потоки, если current-thread-count < ideal-thread-count и все существующие потоки заняты выполнением задач.

Предполагая, что вы создаете все свои потоки одновременно, вам нужно передать рабочую функцию каждому из потоков для выполнения.Эта рабочая функция будет ждать, пока задачи станут доступны, а затем выполнять их.Поскольку функция либо выполняет задачу, либо ожидает ее, она не вернет и поток не будет уничтожен.

Пул потоков может отслеживать очередь задач и управлять условием ожидания, которое указывает, когда в очереди есть доступные задачи.Каждая рабочая функция потока ожидает выполнения условия ожидания, и когда появляется доступная задача, она просыпается и пытается выполнить задачу.Вам нужно будет выполнить некоторую синхронизацию;самым простым способом было бы попытаться найти доступную реализацию пула потоков, например, в Windows (Vista +, я думаю) или в QtConcurrent, которая позволила бы вам просто передать задачу, вызвать run и позволить OS / library обо всем беспокоиться.

Последующее редактирование:

Проверьте http://threadpool.sourceforge.net/

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top