如何在类中使用pthread_mutex及其函数?

时间:2011-05-25 04:47:42

标签: c++ class locking pthreads mutex

我已经搜索了几个小时的解决方案,但找不到简单的答案。 我有一个使用pthreads的类。实际的函数指针在类中是静态的,我需要锁定一个互斥锁,因为到目前为止我得到了“奇怪的”结果(参数没有被正确传递)。

然而,pthread_mutex_lock和unlock将不会在给予该线程的函数内工作,因为它在一个静态成员函数中,但是我不能将该函数设置为非静态函数,因为它在类中不起作用,我无法移动它在课外,因为它无法访问所需的信息。

以下代码应解释:

class Fight{

     pthread_mutex_t thread_mutex;
     static void *thread_run_fighter(void *temp);

  public:

    Fight();
    bool thread_round(Individual &a, int a_u, Individual &b, int b_u);
    std::vector<Individual> tournament();
  };

和cpp文件:

    Fight::Fight(){
       thread_mutex = PTHREAD_MUTEX_INITIALIZER;
    }

    bool Fight::thread_round(Individual &a, int a_u, Individual &b, int b_u){

    if (a.saved and b.saved){
       a.uniform = a_u;
       b.uniform = b_u;
       Individual *one = &a;
       Individual *two = &b;      
       pthread_t a_thread, b_thread;
       int a_thread_id, b_thread_id;
       a_thread_id = pthread_create(&a_thread,NULL,Fight::thread_run_fighter,(void*) one);
       b_thread_id = pthread_create(&b_thread,NULL,Fight::thread_run_fighter,(void*) two);

       pthread_join( a_thread, NULL);
       pthread_join( b_thread, NULL); 
       return true;
    }
    else{
       return false;
    }
   }

   void *Fight::thread_run_fighter(void *temp){

     Individual *indiv;
     indiv = (class Individual*)temp;
     pthread_mutex_lock( &thread_mutex );
     indiv->execute(indiv->uniform);
     pthread_mutex_unlock( &thread_mutex );

   }

如果有人能对此有所了解,我将非常感激。我现在已经被困了几个小时,我找不到任何信息。 谢谢!

4 个答案:

答案 0 :(得分:4)

由'不起作用'我假设你的意思是它不会编译,因为你试图在static成员函数中使用实例成员。

但更大的问题是你为什么要尝试使用线程呢?

你拥有的线程函数完全受到互斥锁的保护 - 只需调用

即可获得相同(或更好)的性能
a.execute(a.uniform);
b.execute(b.uniform);

而不是旋转线程然后等待它们完成。


但是如果你真的想要使用线程(也许你正在学习它们)并且你希望你的静态成员函数能够处理实例成员,那么这里有一些指针。要使其工作,您需要以某种方式将Fight对象的实例传递给static线程函数:

// somewhere in `class Fight` definition:
//
// a structure that will let you pass a Fight* instance pointer
//  along with an Individual* to work on in the the
//  thread function

struct context {
    Fight* me;
    Individual* indiv;
};



// ...

// in Fight::thread_round():
//  package up data to pass to the thread function
context one = {this, &a };  // instead of Individual *one = &a;
context two = {this, &b };  // instead of Individual *two = &b;

最后,Fight::thread_run_fighter()

void *Fight::thread_run_fighter(void *temp)
{
    // pull out the Fight object instance and the Individual
    //  object to work on
    context* ctx = (context*) temp;
    Individual *indiv = ctx->indiv;
    Fight* me = ctx->me;

    // do the work (in a pretty serialized fashion, unfortunately)
    pthread_mutex_lock( &me->thread_mutex );
    indiv->execute(indiv->uniform);
    pthread_mutex_unlock( &me->thread_mutex );

    return 0;
}

答案 1 :(得分:2)

我想问的第一个问题:你需要便携式代码吗?如果是,则永远不要将C ++函数传递给pthread_create。原因:pthread_create的接口需要声明为extern“C”的函数,并且你很幸运(感谢x86 :))静态成员方法适合这种情况,但不能保证在其他平台或编译器上也是如此。

第二,你在创建互斥锁之后调用了thread_mutex = PTHREAD_MUTEX_INITIALIZER;,据我所记,标准说只允许在初始化时使用。{/ p>

最后,不允许pthread_mutex_lock( &thread_mutex )使用静态方法,因为静态方法无法访问对象的非静态成员,因此您需要将指针传递给您的对象。您可以将pthread_mutex_t thread_mutex;void *thread_run_fighter(void *temp);声明为全局,因为我认为在这种情况下这将是最简单的方式。

还有一些注意事项:boost :: threads怎么样?我认为使用它而不是创建自己的解决方案会更好......

答案 2 :(得分:1)

我认为您错过的只是使用&indiv->thread_mutex而不是省略indiv->对象。

编辑:请注意,使用静态演员而不是C风格的“霰弹枪”演员可能会更好:Individual *indiv = static_cast<Individual*>(temp);

答案 3 :(得分:0)

您使用非静态thread_run_fighter的静态thread_mutex内部。 thread_mutex必须在使用之前使用pthread_mutex_init创建。