我一直在阅读和学习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在整个程序执行期间没有变化。或者它是否在函数内部改变它?
答案 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 *
与==
进行比较,看看它们是否引用相同的字符串。如果您打印出j
和k
,您将获得不同的价值。
类似地,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);
...
}