例程何时传递给pthread_create?

时间:2017-06-23 04:41:07

标签: c pthreads posix

给出以下代码

#include <pthread.h>

void *pt_routine(void *arg)
{
    pthread_t *tid;
    tid = (pthread_t *) arg;
    /* do something with tid , say printf?*/
    /*
    printf("The thread ID is %lu\n", *tid);
    */
    return NULL;
}

int main(int argc, char **argv)
{
    int rc;
    pthread_t tid;
    rc = pthread_create(&tid, NULL, pt_routine, &tid);
    if (rc)
    {
        return 1;
    }
    printf("The new thread is %lu\n", tid);
    pthread_join(tid, NULL);
    return 0;
}

例程总是可以得到正确的tid吗?

当然我可以使用pthread来获取自我ID,但我只是想知道例程何时运行。

2 个答案:

答案 0 :(得分:4)

嗯,实际上有两个问题:

  • 首先执行哪个线程
  • 将在新线程启动之前保存线程ID

这个答案涉及Linux,因为我没有任何其他平台可用。可以找到第一个问题的答案in the manuals

  

除非是实时的          呼叫后,正在使用调度策略          pthread_create(),它是不确定的线程 - 调用者或者          新线程将在下一次执行。

所以很明显,在你的情况下,首先实际运行哪个线程是不确定的。现在,另一个问题是如何实现pthread_create - 如果它可以以某种方式创建一个休眠线程,首先存储它的id,然后再启动它?

好吧,linux使用clone系统调用创建新线程:

clone(child_stack=0x7f7b35031ff0, 
      flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM
          |CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID,
      parent_tidptr=0x7f7b350329d0,
      tls=0x7f7b35032700,
      child_tidptr=0x7f7b350329d0) = 24009

现在,似乎线程ID与clone调用的指针一起存储,但似乎child_tidptr没有引用地址 tid,好像我打印它,地址不同;这是pthread库中的一些内部变量;在 tid系统调用在父线程中返回后,clone将更新

事实上,pthread_self说的如下:

  

pthread_self()返回的线程ID不是一回事          作为调用gettid(2)返回的内核线程ID。

这确认了内核线程ID与pthread_t s

不同

因此,除了POSIX spec不支持这一点之外,Linux平台上实际上没有这样的保证 - 需要在父线程中设置tid <{1}}返回后,否则不会立即知道孩子的线程ID - 但这也意味着如果孩子是第一个执行后的孩子返回,那么线程id可能还没有在那里设置。

答案 1 :(得分:2)

pt_thread()将在调用pthread_create()后的某个任意点开始执行 - 包括它可能在pthread_create()返回调用代码之前开始运行。并且无法保证pthread_create()实现将在线程开始执行之前更新tid变量。

因此,您的代码中没有任何内容可确保pt_routine()正确读取tid值。您需要使用某种同步来确保在没有数据争用的情况下正确发生。或者你可以让线程调用pthread_self()

请参阅the POSIX spec for pthread_create()的“应用程序使用情况”部分:

  

在新创建的线程开始执行之前,对实现没有要求创建的线程的ID可用。调用线程可以通过pthread_create()函数的返回值获取创建的线程的ID,新创建的线程可以通过调用pthread_self获取其ID