创建另一个线程后,Main()线程ID不同

时间:2014-05-12 01:46:01

标签: c multithreading pthreads

我一直在阅读和学习POSIX线程,并尝试编写一些简单的代码来更好地理解它。

#include <stdio.h> /* standard I/O routines */
#include <pthread.h> /* pthread functions and data structures */

/* function to be executed by the new thread */
void* PrintHello(void* data)
{
    pthread_t tid = (pthread_t)data;
    printf("Hello from new thread  %d - got %d\n", pthread_self(), tid);
    pthread_exit(NULL); /* terminate the thread */
}

int main(int argc, char* argv[])
{
    int rc; /* return value */
    pthread_t thread_id;
    int  tid;   

    thread_id = pthread_self();
    printf("FLAG = %d ", thread_id);

    /* create a new thread that will execute 'PrintHello' */
    rc = pthread_create(&thread_id, NULL, PrintHello, (void*)thread_id);
    if(rc) /* could not create thread */
    {
        printf("\n ERROR: return code from pthread_create is %u \n", rc);
    exit(1);
    }
    printf("\n   Created new thread (%d) ... \n",  thread_id);
    pthread_exit(NULL); /* terminate the thread */
}

对于此代码,我得到以下输出:

FLAG = 363480832 
   Created new thread (355198720) ... 
Hello from new thread  355198720 - got 363480832

困扰我的是thread_id 363480832成为355198720,与thread_id调用的函数main相同的原因PrintHello() {1}})。我假设线程id在整个程序执行期间没有变化。或者它是否在函数内部改变它?

3 个答案:

答案 0 :(得分:1)

如果您使用pthread_t执行任何操作,而不是将其传递给需要一个的功能,那么您就会做错事。只有pthreads API知道如何正确使用pthread_t。它们可以具有任何便于实施的内部结构。

作为C语言构造,pthread_t的行为更像char *。必要的语言结构使其表现得像std::string不存在。所以你必须像char *一样对待它。

char *以某种方式包含字符串,但您必须了解其实现以获取该值。考虑:

char *j = "hello";
char *k = strdup (j);
if (j == k)
   printf ("This won't happen\n");
printf ("%d\n", j);
printf ("%d\n", k); // these won't be equal

您无法将char *==进行比较,看看它们是否引用相同的字符串。如果您打印出jk,您将获得不同的价值。

类似地,pthread_t以某种方式引用一个特定的线程。但你必须了解如何获得价值。两个pthread_t可以具有不同的表观值,但仍然引用相同的线程,因为两个char *可以具有不同的表观值,但仍然引用相同的字符串。

正如您将两个char *strcmp进行比较一样,如果您想知道它们是否引用相同的字符串值,则将两个pthread_t与{{{ 1}}告诉他们是否引用同一个帖子。

所以这行代码毫无意义:

pthread_equal

printf("FLAG = %d ", thread_id); 不是整数,您无法使用pthread_t格式说明符打印它。 POSIX没有可打印的线程ID。如果你想要一个,你需要编码一个(可能使用%d)。

答案 1 :(得分:0)

在C中,参数按值传递。特别是,参数(void *)thread_id是在调用pthread_create之前评估的表达式,因此pthread_create由于{{1}而写入thread_id的事实作为第一个参数传递是无关紧要的。如果您将&thread_id而不是&thread_id作为参数传递给新线程启动函数,并在那里取消引用它,那么您可能看到您想要的效果;但是,我不清楚(void *)thread_id是否需要在新线程开始之前通过第一个参数写入新线程id,因此可能存在数据竞争如果你这样做的话。

此外,请注意David的答案也是正确的。以这种方式打印线程ID是无效的,因为它们是正式的不透明类型。

答案 2 :(得分:0)

在这一行:

rc = pthread_create(&thread_id, NULL, PrintHello, (void*)thread_id);

如手册所述,pthread_create()应将创建的线程的ID存储在thread_id引用的位置。在此示例中,它将被修改为355198720,这是新线程PrintHello()的tid。

此外,将PrintHello的参数更改为:

可能更好
rc = pthread_create(&thread_id, NULL, PrintHello, (void*)&thread_id);

并在PrintHello()中,它将是:

void* PrintHello(void* data)
{
    pthread_t tid = (pthread_t)(*data);
    ...
}