Подтвердить что ты не робот

(простой) boost_group вопрос

Я пытаюсь написать довольно простое многопоточное приложение, но новичок в создании библиотеки потоков. Простая тестовая программа, над которой я работаю:

#include <iostream>
#include <boost/thread.hpp>

int result = 0;
boost::mutex result_mutex;

boost::thread_group g;

void threaded_function(int i)
{
    for(; i < 100000; ++i) {}

    {
        boost::mutex::scoped_lock lock(result_mutex);
        result += i;
    }
}

int main(int argc, char* argv[])
{
    using namespace std;

    // launch three threads
    boost::thread t1(threaded_function, 10);
    boost::thread t2(threaded_function, 10);
    boost::thread t3(threaded_function, 10);

    g.add_thread(&t1);
    g.add_thread(&t2);
    g.add_thread(&t3);

    // wait for them
    g.join_all();

    cout << result << endl;

    return 0;
}

Однако, когда я компилирую и запускаю эту программу, я получаю вывод

$ ./test 
300000
test: pthread_mutex_lock.c:87: __pthread_mutex_lock: Assertion `mutex->__data.__owner == 0' failed.
Aborted

Очевидно, результат верен, но я беспокоюсь об этом сообщении об ошибке, особенно потому, что реальная программа, которая имеет по существу ту же структуру, застревает в точке join_all(). Может кто-нибудь объяснить мне, что происходит? Есть ли лучший способ сделать это, то есть запустить несколько потоков, сохранить их во внешнем контейнере, а затем дождаться их завершения до продолжения программы?

Спасибо за вашу помощь.

4b9b3361

Ответ 1

Я думаю, что проблема вызвана деструктором thread_group, который вызывается при выходе из вашей программы. Группа потоков хочет взять на себя ответственность за разрушение объектов потока. См. Также в документации boost:: thread_group.

Вы создаете свои потоковые объекты в стеке как локальные переменные в области вашей основной функции. Таким образом, они уже были разрушены, когда программа выходит, и thread_group пытается их удалить.

В качестве решения создайте объекты потока в куче с новыми и дайте thread_group позаботиться об их уничтожении:

boost::thread *t1 = new boost::thread(threaded_function, 10);
...
g.add_thread(t1);
...

Ответ 2

Если вам не нужен дескриптор ваших потоков, попробуйте использовать thread_group:: create_thread(), который облегчает необходимость управления потоком вообще:

// Snip: Same as previous examples

int main(int argc, char* argv[])
{
    using namespace std;

    // launch three threads
    for ( int i = 0; i < 3; ++i )
        g.create_thread( boost::bind( threaded_function, 10 ) );

    // wait for them
    g.join_all();

    cout << result << endl;

    return 0;
}

Ответ 3

add_thread() принимает право собственности на поток, который вы передаете. Группа потоков удаляет поток. В этом примере вы удаляете память, выделенную в стеке, в значительной степени заглавное преступление.

Функция участника add_thread()

void add_thread (thread * thrd);

Предпосылкой

Выражение delete thrd равно хорошо сформированный и не приведет к undefined.

Эффекты:

Возьмите ответственность за boost:: thread объект, на который указывает thrd, и добавьте его к группе.

Постусловие

this- > size() увеличивается на единицу.

Не уверен, что это неправильно в вашем коде, или это просто пример ошибки. В противном случае код выглядит нормально.

Ответ 4

Похоже, что ничего выше не ответил на вопрос.

Я встретил подобную проблему. Следствием этого предупреждения (pthread_mutex_lock.c: 87: __pthread_mutex_lock: Assertion `mutex → _ data._owner == 0 'не удался. Aborted) заключается в том, что иногда программа течет потоками и вызывает исключение boost_resource_error.

Похоже, что программа продолжает выполняться после join_all(), хотя большая часть потоков все еще запущена (не завершена).