pthread_mutex_t, поскольку член класса вызывает взаимоблокировку

0

Я новичок в параллельных вычислениях, поэтому я играю с pthread и mutexes. Выполнение следующего кода приводит к взаимоблокировке. Может ли кто-нибудь объяснить мне, почему, и как к этому правильному пути? Моя цель - защитить переменные-члены от перекрестного письма. Заранее большое спасибо!

#include <pthread.h>
#include <iostream>

class mutex_class
{

    public:
        mutex_class();
        void print_stars(int count);
        void print_dots(int count);

    private:
        pthread_mutex_t mutex;

};

mutex_class::mutex_class()
{
    pthread_mutex_t mutex;
    pthread_mutex_init (&mutex, NULL);
}

void mutex_class::print_stars(int count)
{
    pthread_mutex_lock(&this->mutex);
    for(int i=0; i<count; i++)
    {
        std::cout << "*" << std::flush;
    }
    pthread_mutex_unlock(&this->mutex);
}

void mutex_class::print_dots(int count)
{
    pthread_mutex_lock(&this->mutex);
    for(int i=0; i<count; i++)
    {
        std::cout << "." << std::flush;
    }
    pthread_mutex_unlock(&this->mutex);
}

void* call_dots(void* m)
{
    (*(mutex_class*)m).print_dots(20);
}

void* call_stars(void* m)
{
    (*(mutex_class*)m).print_stars(20);
}

int main()
{
    mutex_class m1 = mutex_class();
    pthread_t t1, t2;
    pthread_create(&t1, NULL, call_dots, (void*)&m1);
    pthread_create(&t2, NULL, call_stars, (void*)&m1);
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    return(0);
}
  • 0
    Рассматривали ли вы обновление вашего компилятора (например, до GCC 4.9.x) и использование C ++ 11? У него есть std :: thread и т. Д.
  • 0
    Если вы используете C ++, используйте std :: thread. Гораздо проще в некоторых отношениях.
Показать ещё 2 комментария
Теги:
mutex
pthreads
deadlock

1 ответ

7

Проблема здесь:

mutex_class::mutex_class()
{
    pthread_mutex_t mutex;             // <<< remove this line
    pthread_mutex_init (&mutex, NULL);
}

Вы инициализируете локальный мьютекс и оставляете переменную-член неинициализированной.

Если вы почему-то не застряли в прошлом, подумайте об использовании стандартной библиотеки потоков C++; он более портативен и менее подвержен ошибкам, чем обманывает API-интерфейсы C-стиля. Здесь ваша программа в более C++ идиоме:

#include <thread>
#include <mutex>
#include <iostream>

class mutex_class
{
    public:
        // No need for a special constructor

        void print_stars(int count);
        void print_dots(int count);

    private:
        std::mutex mutex;
};

void mutex_class::print_stars(int count)
{
    std::lock_guard<std::mutex> lock(mutex);  // unlocks automatically
    for(int i=0; i<count; i++)
    {
        std::cout << "*" << std::flush;
    }
}

void mutex_class::print_dots(int count)
{
    std::lock_guard<std::mutex> lock(mutex);  // unlocks automatically
    for(int i=0; i<count; i++)
    {
        std::cout << "." << std::flush;
    }
}

// No need to muck around with C-style 'void*' functions

int main()
{
    mutex_class m1;
    std::thread t1([&]{m1.print_dots(20);});
    std::thread t2([&]{m1.print_stars(20);});
    t1.join();
    t2.join();
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню