《C++并发实例》2.5 标识线程
线程标识符的类型为 std:: thread ::id ,可以通过两种方式检索。首先,可以通过调用线程关联的 std::thread 对象的成员函数 get_id() 来获取标识符。如果 std:: thread 对象没有关联的执行线程,则调用 get_id() 的将返回默认构造的 std:: thread::id 对象,这表示“非线程”。可以通过调用 std::this_thread:: get_id() 来获取当前线程的标识符,该定义在
std:: thread::id 类型的对象可以自由复制和比较;这就是它们的功能。如果两个 std:: thread::id 对象相等,则它们代表同一个线程,或者两者都是“非线程”。如果两个对象不相等,则它们代表不同的线程,或者一个代表线程,另一个代表“非线程”。
线程库并不限制你检查线程标识符是否相同; std:: thread::id 对象了提供完整的比较运算方法,提供了对所有值进行排序。允许它们作为相关容器中的key来使用,或者您认为合适的方法进行排序。比较运算符也可以用于 std:: thread::id 的不同值比较,它可以像你直观感知地那样:如果 a<b 且 b<c,则 a<c,依此类推。标准库还提供了 std::hash<std:: thread::id> ,因此 std:: thread::id 类型的值也可以做无序容器中的key。
std:: thread::id 实例通常用于检查线程是否需要执行某些操作。例如,如果使用线程来划分工作(如listing 2.8),启动其他线程的初始线程可能需要在执行时有稍微不同。这种情况下可以在启动其他线程前调用 std::this_thread::get_id() 并保存标识符,然后算法的核心部分(对所有线程都是公共的)可以根据存储的值检查自己的线程 ID :
std::thread::id master_thread;
void some_core_part_of_algorithm()
{
if(std::this_thread::get_id()==master_thread)
{
do_master_thread_work();
}
do_common_work();
}
或者,当前线程的 std:: thread::id 可以作为操作的一部分存储在数据结构中。后续对象通风数据结构的操作可以通过检查线程 id 来确定需要或允许哪些操作。
类似地,线程 ID 可以用作关联容器的key,用于数据需要绑定相关的线程,或者替换本地线程不恰当的存储机制。例如,这样的容器可以用来存储每个运行线程的信息,或者用于在线程之间传递信息。
在大多数情况下, std:: thread::id 足以作为线程的通用标识符;仅当标识符具有与其关联的语义(例如作为数组的索引)时才需要替代方案。您甚至可以将 std:: thread::id 的实例写入输出流,例如 std::cout:
std::cout<<std::this_thread::get_id();
确切的输出严格依赖于实现;这个标准只能确保相同 id 的线程应该产生相同的输出,而那些不相等的线程 ID 应该产生不同的输出。因此,这主要用于调试和日志记录,但这些值没有特别的意义,因此也没有什么可分析的。
2.6 总结
在本章中,我介绍了使用 C++ 标准库进行线程管理的基础知识:启动线程、等待它们结束,以及不等待它们结束,因为您希望它们在后台运行。您还了解了如何在启动线程时将参数传递到线程函数中、如何将管理线程的所有权从代码的一部分转移到另一部分,以及如何使用线程组来划分工作。最后,我讨论了识别线程,以便将通信不方便的数据或行为用另一种方式与特定线程关联。虽然你可以使用完全独立的线程做很多事情,每个线程都操作单独的数据,例如listing 2.8,但有时需要在线程运行时在线程之间共享数据。第 3 章讨论了有关在线程之间直接共享数据的问题,而第 4 章则讨论了共享数据常用的异步操作。
浙公网安备 33010602011771号