2

我正在使用 C++ 和 pthread,我需要找出创建 pthread 的顺序,我需要一个唯一的整数来告诉我首先创建哪个 pthread,第二个等等。

我的第一个想法是使用pthread_self(),尽管这个函数返回一个唯一的 id,它几乎是一个巨大的随机数。

我的第二个想法是传递我在循环中的 create 方法中使用的计数器:

pthread_t pthreads[pthreadsNum]; 
    for(int i = 0; i < pthreadsNum; i++){
        if (pthread_create(&pthreads[i], NULL, process, (void *)&i) != 0){
            cerr << "Error in pthread creation" << endl;
            return PTHREAD_CREATION_FAILED;
        }
    }

但是,这也不起作用。在我的函数中,process我尝试打印i计数器的值,但我感到困惑。显然,计数器在一些 pthread 接收它和混乱规则时得到更新:

void *process(void* arg_ptr)
{
  int i = *((int*)arg_ptr);
  cout << i << endl;
  //rest of code
}

给我随机输出:3 3 4 3 以及这个相同随机输出的其他组合。

总之,我有以下问题:

1 - 我做错了什么?

2 - 如何安全有效地通过柜台?

3 - 是否有另一种解决方案来获取创建 pthread 的顺序?

在此先感谢您的帮助:S

4

3 回答 3

2

计数器在一些 pthread 正在接收它和混乱规则时得到更新

是的,这就是在没有同步的情况下使用并行性最终得到的结果:事情永远不会按照您期望的顺序发生。

在您的情况下,将计数器传递给线程的一种简单方法是将其转换为指针。为确保您使用的整数类型与指针大小相同,请使用uintptr_t(标准保证指针和 (u)intptr_t 之间的转换没有任何损失):

#include <stdint.h>

for (uintptr_t i = 0; i < pthreadsNum; ++i) {
    if (pthread_create(&pthreads[i], NULL, process, reinterpret_cast<void*>(i)) != 0) {
        ...

void* process(void* arg_ptr) {
    uintptr_t i = reinterpret_cast<uintptr_t>(arg_ptr);
    ...

但是 cHao 的评论非常中肯:如果您需要对线程的执行顺序进行如此多的控制,那么您就有问题了。更好地使用同步(互斥锁、条件变量等)来保护用于线程间通信的关键数据结构(例如消息队列、其他复杂对象甚至简单的标量),您将不需要这种精细控制。

于 2013-03-11T19:48:09.737 回答
2

您传入了 的地址i,当您的线程读取 的值时i,它很可能已被更改。因为您创建的线程和运行循环并更新值的主线程i并行运行。

如果我这样做,我会这样做:

pthread_t pthreads[pthreadsNum];
int ids[pthreadsNum];
for(int i = 0; i < pthreadsNum; i++){
    ids[i] = i;
    if (pthread_create(&pthreads[i], NULL, process, (void *)&ids[i]) != 0){
于 2013-03-11T19:50:37.280 回答
0

首先,有两个问题:为什么需要这些信息?你想解决什么问题?

话虽如此,为什么不简单地包装pthread_create一个函数,该函数维护一些数据结构(例如 std::vector<> 或链表)。包装器调用pthread_create,并将每个创建的线程的线程id添加到数据结构中?请记住添加一些锁定/序列化。以及删除已退出线程的代码(如果需要)。

最后,当您需要创建的“顺序”时,只需在您的数据结构中找到线程 id 的“索引”即可。

于 2013-03-11T22:13:46.210 回答