在LINUX系统中,POSIX threads库提供了pthread_t来标识一个线程,通过pthread_self()可以得到,如下:
#include <iostream>
#include <pthread.h>
using namespace std;
void* thread_func(void*)
{
//pthread_t other_thread_id = pthread_self();
//cout << "other_thread_id=" << other_thread_id << endl;
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t t1, t2;
pthread_create(&t1, NULL, thread_func, NULL);
cout << t1 << endl;
pthread_join(t1, NULL);
//pthread_create(&t2, NULL, thread_func, NULL);
//cout << t2 << endl;
//pthread_join(t2, NULL);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
得到结果:
typedef unsigned long int pthread_t;
这个数值很大。而且比较两个线程是否相同也需要用pthread_equal(pthread_t t1, pthread_t t2)来比较。
那么,使用pthread_t来标识线程id是否是最合适的?
答案是否
原因:这个pthread_t的值很大,无法作为一些容器的key值。
pthread_t是由POSIX pthread库内部提供的,只在进程内部有意义,无法关联操作系统的任务调度之类的信息。比方说在/proc查找不到关于pthread_t得到的task。
glibc的Pthreads实现实际上把pthread_t作为一个结构体指针,指向一块动态分配的内存,但是这块内存是可以反复使用的,也就是说很容易造成pthread_t的重复。也就是说pthreads只能保证同一进程内,同一时刻的各个线程不同;不能保证同一个进程全程时段每个线程具有不同的id,不能保证线程id的唯一性。下面可以通过一个例子:
#include <iostream>
#include <pthread.h>
using namespace std;
void* thread_func(void*)
{
//pthread_t other_thread_id = pthread_self();
//cout << "other_thread_id=" << other_thread_id << endl;
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t t1, t2;
pthread_create(&t1, NULL, thread_func, NULL);
cout << t1 << endl;
pthread_join(t1, NULL);
pthread_create(&t2, NULL, thread_func, NULL);
cout << t2 << endl;
pthread_join(t2, NULL);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
运行结果:
上述原因显然表明pthread_t是不适合作为线程的标识的。所以应该使用什么来标识呢。
首先对于进程id,有函数getpid返回的pid_t来标识。那么线程有没有类似的gettid来标识呢。
在LINUX系统中,建议使用gettid系统调用的返回值作为线程id,这么做的原因:
返回值是一个pid_t,其值是一个很小的整数,方便输出。
在linux系统中,它直接标识内核任务调度id,可通过/proc文件系统中找到对应项:/proc/tid 或者 /proc/pid/task/tid,方便定位到具体线程
任何时刻都是唯一的,并且由于linux分配新的pid采用递增轮回办法,短时间内启动多个线程也会具有不同的id
0是非法值,操作系统第一个进程init的pid是1
glibc没有封装这个gettid,需要我们手动封装。
举例:
#include <iostream>
#include <pthread.h>
#include <sys/syscall.h>//获取线程id的系统调用头文件
#include <sys/types.h>
#include <unistd.h>
using namespace std;
void* thread_func(void*)
{
//获取线程id的系统调用
cout << syscall(__NR_gettid) << endl;
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t t1, t2;
pthread_create(&t1, NULL, thread_func, NULL);
cout << t1 << endl;
pthread_join(t1, NULL);
pthread_create(&t2, NULL, thread_func, NULL);
cout << t2 << endl;
pthread_join(t2, NULL);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
结果:
和pthread_t的描述完全不一样。
使用比较优雅的方式是定义一个gettid的宏
#include <sys/syscall.h>//获取线程id的系统调用头文件
#include <sys/types.h>
#include <unistd.h>
//定义宏
#define gettid() syscall(__NR_gettid)
1
2
3
4
5
6
验证TID是否正确的方法:
查看进程pid
(1) ps ux | grep prog_name
(2) pgrep prog_name
查看线程tid
(1) ps -efL | grep prog_name
(2) ls /proc/pid/task
————————————————
版权声明:本文为CSDN博主「ZgZeQi」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zeqi1991/article/details/81611919
来源:oschina
链接:https://my.oschina.net/u/4000302/blog/4321594