【问题标题】:pthread_mutex_t as class member causes deadlockpthread_mutex_t 作为类成员导致死锁
【发布时间】:2014-09-09 12:09:34
【问题描述】:

我是并行计算的新手,所以我在玩 pthread 和互斥锁。 运行以下代码会导致死锁。谁能解释我为什么,以及如何以正确的方式做到这一点?我的目标是保护成员变量不被交叉写入。 提前非常感谢!

#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);
}

【问题讨论】:

  • 您是否考虑过升级您的编译器(例如升级到GCC 4.9.x)并使用C++11?它有std::thread等等等等。
  • 如果您使用 C++,请使用 std::thread。在某些方面更容易。
  • 或者只是修复你的代码。删除构造函数中的 pthread_mutex_t mutex;。本地 var 隐藏了未初始化的类成员。
  • 如果您想使用 C++11 风格的线程,但还不能使用足够新的编译器,boost::thread 非常相似,并且在更旧的系统上运行良好。

标签: c++ pthreads mutex deadlock


【解决方案1】:

问题出在这里:

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

您正在初始化一个本地互斥体,但未初始化成员变量。

除非您因某种原因被困在过去,请考虑使用标准 C++ 线程库;它比使用 C 风格的 API 更便携,更不容易出错。这是你的程序更 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();
}

【讨论】:

    猜你喜欢
    • 2018-04-20
    • 2012-09-20
    • 2018-06-04
    • 2016-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多