C++有了支持多线程的thread
库,只需要包含头文件#include <thread>
就能使用,那么如何获取一个线程的id呢?
thread
中提供了std::thread::get_id()
这个方法,这个方法返回的是_M_id
,类型是std::thread::id
:
private:
id _M_id;
thread::id
get_id() const noexcept
{ return _M_id; }
那么这个thread::id
是什么呢?这是一个在thread
内部定义的类:
/// thread
class thread
{
public:
typedef __gthread_t native_handle_type;
struct _Impl_base;
typedef shared_ptr<_Impl_base> __shared_base_type;
/// thread::id
class id
{
native_handle_type _M_thread;
public:
id() noexcept : _M_thread() { }
explicit
id(native_handle_type __id) : _M_thread(__id) { }
private:
friend class thread;
friend class hash<thread::id>;
friend bool
operator==(thread::id __x, thread::id __y) noexcept
{ return __gthread_equal(__x._M_thread, __y._M_thread); }
friend bool
operator<(thread::id __x, thread::id __y) noexcept
{ return __x._M_thread < __y._M_thread; }
template<class _CharT, class _Traits>
friend basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id);
};
}
可以看到std::thread::id
中的唯一成员变量是_M_thread
,类型是native_handle_type
,它是__gthread_t
的typedef
,这是一种gcc内置的类型,我们暂时把这个类型当unsigned long long
来看待。但是这个成员变量是私有的,我们拿不出来。唯一共有的东西是它的构造函数,但是没有什么用。
幸好,它重载了<<
输出运算符,这个还是std::thread::id
的一个友元函数,这就好办了,用stringstream
把_M_thread
拿到。当然你可以用std::cout
直接输出。
template<class _CharT, class _Traits>
inline basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id)
{
if (__id == thread::id())
return __out << "thread::id of a non-executing thread";
else
return __out << __id._M_thread;
}
以上是operator <<
的具体实现,可以看到确实输出了了_M_thread
。
测试如下:
#include <thread>
typedef unsigned long long ULL;
std::string getThreadIdOfString(const std::thread::id & id)
{
std::stringstream sin;
sin << id;
return sin.str();
}
ULL getThreadIdOfULL(const std::thread::id & id)
{
return std::stoull(getThreadIdOfString(id));
}
int main()
{
std::thread::id id = std::this_thread::get_id();
std::cout << "cout ----- id : " << id << std::endl;
std::cout << "getThreadIdOfString ----- id : " << getThreadIdOfString(id) << std::endl;
std::cout << "getThreadIdOfULL ----- id : " << getThreadIdOfULL(id) << std::endl;
return 0;
}
其实还有更简单的方法,我们得到线程id的目的是什么,是为了标识这个线程,那么并不一定要用_M_thread
。可以从上面的源码看到,class hash<thread::id>
是thread::id
的友元类,也就是说hash
为std::thread::id
做了特化,因此,我们直接用hash<std::thread::id>()(id)
来生成这个唯一的标识。
// DR 889.
/// std::hash specialization for thread::id.
template<>
struct hash<thread::id>
: public __hash_base<size_t, thread::id>
{
size_t
operator()(const thread::id& __id) const noexcept
{ return std::_Hash_impl::hash(__id._M_thread); }
};
以上是hash<thread::id>
的特化和具体实现。
测试如下:
#include <bits/stdc++.h>
#include <thread>
int main()
{
std::thread::id id = std::this_thread::get_id();
std::cout << std::hash<std::thread::id>()(id) << std::endl;
std::cout << "cout ----- id : " << id << std::endl;
return 0;
}