在知道如何获得一个线程的id之前,你必须首先知道C++中线程id的两种形式。这相当于知道当线程没有运行时获得什么id,以及当线程运行时获得什么id。运行意味着执行。ID(代表IDentifier)是识别事物的东西。在C++中,线程ID的名称是id,小写的。
对于C++中的线程,id是一个具有数据成员和成员函数的对象。这个id对象有一个文本代码,这就是人们通常认为的id。id对象使用<<操作符,将文本代码发送到cout对象(终端)。从线程未运行时到运行时,id对象及其文本代码是不同的。
线程是一个类,其中id对象是一个数据成员。id对象可以通过以下语法获得。
thread::get_id()
语法 "thread::get_id() "可以在线程未运行时使用,也可以在线程运行时使用,它将为两种不同的情况提供不同的对象和相应的文本代码。
在线程运行时,在线程体中获取线程ID的方法是使用语法。
this_thread::get_id()
所有正在运行的线程都有不同的id对象和相应的文本代码。所有未运行的线程对于同一个程序都有相同的对应文本代码。虽然它们有相同的文本代码,但所有未运行的线程都有不同的id对象,因为对象是引用而不是指针。
一个正在运行的线程被称为执行线程。
要编译一个线程的程序,用g++编译器,使用类似的命令。
g++ -std=c++2a temp.cpp -lpthread -o temp
这篇文章解释了在C++中获得不同线程ID的不同方法,首先是对什么是线程的总结。
文章内容
线程总结
一个线程是一个顶层函数的外壳。一个线程是由线程类实例化的。顶层函数的名称是线程对象构造函数的一个参数。C++中的main()函数也是一个顶层函数。所以main()函数的行为就像主线程。下面的程序显示了两个线程,main()函数是其中之一。
#include <iostream>
#include <thread>
using namespace std;
thread thr;
void fun() {
cout <<"This is line A." <<endl;
cout <<"This is line B." <<endl;
}
int main()
{
thr = thread(fun);
thr.join();
/* statements */
return 0;
}
输出结果是:
This is line A.
This is line B.
顶层函数是fun()和main()。main()就像主线程。顶层函数的名称fun()是主函数中线程构造器three的参数。
程序开始时包含了iostream库。接着是加入线程库。之后的语句确保程序中使用的任何名称都是标准名称空间的,除非另有说明。
接下来,线程库被声明为没有函数调用。然后定义了顶层函数fun()。此后是main()函数的定义。main()中的第一条语句将函数fun()分配给线程thr,并调用该函数。
main()中的第二条语句是连接语句。如果没有这条语句,主线程可能会在没有线程thr运行完成的情况下运行完成。有了这个语句,在该语句被输入的地方,主线程(函数)停止(阻塞),并允许加入的线程(thr)执行完成;然后主线程继续完成自己的任务。试图在没有连接语句的情况下编译程序,最终会出现错误信息,无法编译。
当用语句声明线程时。
thread thr;
时,它不是一个正在运行的线程;没有函数在运行。然而,当线程thr被赋予一个函数名作为参数时,如:。
thr\=thread(fun);
它就成了一个运行的线程。这条语句也是一个函数调用,用于函数fun()。
在主函数的连接语句之后,线程thr已经完成了它的执行,它不再是一个正在运行的线程。在这种状态下,它的id与运行时的id是不同的。
获取线程id
下面的程序显示了当线程不执行时和执行时获取线程id的基本方法。
#include <iostream>
#include <thread>
using namespace std;
thread thr;
void fun() {
cout <<"This is line A." <<endl;
thread::id idR = thr.get_id();
cout <<idR <<endl;
cout <<"This is line B." <<endl;
}
int main()
{
thread::id idD = thr.get_id();
cout <<idD <<endl; cout <<endl;
thr = thread(fun);
thr.join();
//cout <<thr.get_id() <<endl;
/* statements */
return 0;
}
笔者电脑的输出是:
thread::id of a non-executing thread
This is line A.
140362842543872
This is line B.
thr是一个全局变量。它被用于线程three的函数体中,在语句中。
thread::id idR = thr.get_id();
保存获得的线程对象的变量是idR。尽管id是一个实例化的对象,但它也是线程类的一个成员。所以idR的声明必须是。
thread::id idR
并加上分号。这条语句之后的下一条语句是。
cout <<idD <<endl;
操作符,<<获得并插入文本版本的id到cout(终端)。注意:这种情况下的id是在线程运行(执行)时获得的。在线程不执行时获得id的语句是
thread::id idD = thr.get_id();
在main()函数中。它与线程执行函数中的语句相同,只是接收变量idD不同。这条语句是在线程,thr被分配到一个函数之前执行的。这个没有执行的线程的文本id(代码)是。
thread::id of a non-executing thread
在main()函数的执行过程中,线程thr在join语句之后已经完成了自己的执行。于是,"thr.get_id() "应该能够返回该线程不执行时的id。从目前来看,用g++编译的C++程序很难获得已经运行完成的线程的id。这就是为什么上面的代码中join语句后的id语句被注释掉了。
使用this_thread::get_id()
"this_thread:: "是在执行的线程(函数)内编码的。它代表当前正在运行的线程。它后面可以跟一个线程的函数,比如get_id(),以使
this_thread::get_id()
来获得正在运行的线程的id,这个id与线程不运行时的id不同。
"this_thread:: "是在线程的函数体内使用。下面的程序为线程说明了这一点,three。
#include <iostream>
#include <thread>
using namespace std;
thread thr;
void fun() {
cout <<"This is line A." <<endl;
thread::id idR = this_thread::get_id();
cout <<idR <<endl;
cout <<"This is line B." <<endl;
}
int main()
{
thread::id idD = thr.get_id();
cout <<idD <<endl; cout <<endl;
thr = thread(fun);
thr.join();
return 0;
}
作者电脑的输出结果是:
thread::id of a non-executing thread
This is line A.
140199206078208
This is line B.
请注意,在这种情况下,线程名称three并没有在线程函数体内使用。
结论
C++中的线程ID有两种形式。线程执行时的ID与线程不执行时的ID不同。ID(即IDentifier)是识别事物的标志。在C++中,线程ID的名字是id,小写的。这是线程类中的一个数据成员。它不是一个基本对象。它是从自己的类中实例化出来的,属于命名空间,即thread::id。虽然id是一个对象,但它有一个相应的文本形式。该文本形式可以用C++的插入操作符<<插入到cout对象(终端)中。
每个线程有两个不同的ID。一个是当线程正在运行时;另一个是当线程没有运行时。当线程不运行时,ID的文本形式与同一线程运行时的文本形式不同。
C++规范中有多种获取线程ID的方法。然而,截至目前,在g++编译器中,获取id的唯一方法是来自表达式。"threadObject.get_id() "和 "this_thread::get_id()"。"this_thread::get_id() "在执行线程的函数体内使用,其中 "this_thread:: "指的是当前运行的线程。一个正在运行的线程被称为执行线程。