Я новичок в параллельных вычислениях, поэтому я играю с 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);
}
Проблема здесь:
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();
}